cancel
Showing results for 
Search instead for 
Did you mean: 

Java Map Causing error because of ampersand &

Former Member
0 Kudos

I have a Java Map which works perfectly unless the data coming though the mapping is an ampersand ( & ). I tried adding a replaceAll("&","&"), before emitting text but the problem still persist.

When I run the mapping in the IB: Design Test Tool the mapping executes and produces an error of "XML not well-formed". Sure enough if I check the ouput the XML document stops at the element <PartnerName> which contains an ampersand value. If I change the partnername value in the test tool before running the transformation everything works.

Any suggestions?

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Thanks for all the repsonses. This is all new to me so I will have to do some serious reading. It looks like I have two options. The first if I understand correctly would be to keep the program as is but add a replaceAll("&","&"); in the charachters section of the program after the setup of the stringbuffer.

The second is that I need to alter the program to use the javax.xml.transform for outputting the data. This sounds a little tricker but seems like the best method for dealing with the special characters.

I have included my mapping program below:

package package1;

import com.sap.aii.mapping.api.StreamTransformation;

import org.xml.sax.*;

import java.io.*;

import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParserFactory;

import java.util.Map;

import javax.xml.parsers.SAXParser;

public class PrefixChange extends DefaultHandler implements StreamTransformation{

StringBuffer textBuffer;

OutputStream Output;

// Value to be replaced

String shortNS = "PIDX";

String stdPrefix = "ns2";

String xmlStartStr = "<?xml version='1.0' encoding='UTF-8'?>";

private Map map;

public void setParameter(Map param)

{

map = param;

}

// Setup SAX Parser

public void execute (InputStream in, OutputStream out)

throws com.sap.aii.mapping.api.StreamTransformationException

{

SAXParserFactory factory = SAXParserFactory.newInstance();

try

{

SAXParser saxParser = factory.newSAXParser();

Output = out;

saxParser.parse(in, this);

}

catch (Throwable t)

{

t.printStackTrace();

}

}

public void startDocument()

throws SAXException

{

String tag = "";

// Output xml version and encoding

emitText(xmlStartStr);

// Hard return

nl();

}

public void endDocument() throws SAXException {

try {

nl(); // Line Seperator

Output.flush();

} catch (IOException e) {

throw new SAXException("I/O error", e);

}

}

public void startElement(String namespaceURI,

String sName, // simple name

String qName, // qualified name (prefix plus element

Attributes attrs)

throws SAXException

{

echoText();

String eName = sName; // element name

if ("".equals(eName))eName = qName; // not namespace-aware

// Read final element name and replace XI default prefix value

eName = eName.replaceAll(stdPrefix,shortNS);

emitStartTag(eName, attrs);

}

public void endElement(String namespaceURI,

String sName, // simple name

String qName // qualified name

)

throws SAXException

{

echoText();

String eName = sName; // element name

if ("".equals(eName)) eName = qName; // not namespace-aware

// Read final element name and replace XI default prefix value

eName = eName.replaceAll(stdPrefix,shortNS);

emitEndTag("</"eName">");

}

public void characters(char buf[], int offset, int len)

throws SAXException

{

String s = new String(buf, offset, len);

if (textBuffer == null) {

textBuffer = new StringBuffer(s);

} else {

textBuffer.append(s);

}

}

// Simple routine to output text

private void echoText()

throws SAXException

{

if (textBuffer == null) return;

String s = ""+textBuffer.toString();

emitText(s);

textBuffer = null;

}

// Simple routine to generate hard return

private void nl()

throws SAXException

{

String lineEnd = System.getProperty("line.separator");

try

{

Output.write(lineEnd.getBytes());

}

catch (IOException e) {

throw new SAXException("I/O error", e);

}

}

private void emitStartTag(String s, Attributes attrs)

throws SAXException

{

String attr = "";

String tag = "";

int length = attrs.getLength();

int i = 0;

while (i < length){

attr = attr + attrs.getQName(i) + "='" + attrs.getValue(i) + "' ";

i++;

}

// Temporary method of replacing standard XI prefix with PIDX

attr = attr.replaceAll(stdPrefix,shortNS);

if(length > 0){

s = "<"s" "attr">";

emitText(s);

} else {

s= "<"s">";

emitText(s);

}

}

private void emitEndTag(String s)

throws SAXException

{

emitText(s);

}

private void emitText(String str)

throws SAXException

{

try{

Output.write(str.getBytes());

Output.flush();

} catch (IOException e) {

throw new SAXException("I/O error", e);

}

}

private void emitAttrs(String attr) {

printAttrs(attr);

}

private void printAttrs(String attr) {

try {

Output.write(attr.getBytes());

}

catch (IOException e) {

e.notify();

}

}

public static void main (String[] args)

{

try

{

InputStream in = new FileInputStream(new File("PIDXr2.xml"));

OutputStream out = new FileOutputStream(new File("out.xml"));

PrefixChange jmt = new PrefixChange();

jmt.execute(in, out);

}

catch (Exception e)

{

e.printStackTrace();

}

}

}

0 Kudos

Hi!

Check out my latest blog <a href="/people/thorsten.nordholmsbirk/blog/2006/08/10/using-jaxp-to-both-parse-and-emit-xml-in-xi-java-mapping-programs">Using JAXP to both parse and emit XML in XI Java mapping programs</a> for some additional help getting started.

Regards,

Thorsten

Answers (1)

Answers (1)

Former Member
0 Kudos

Hi Netrouter,

Can you post the erroring out part of ur XML here?

cheers,

Prashanth

Former Member
0 Kudos

The XML test file has the following element which is causing an error:

<BillToParty>

<BuyerID>7001</BuyerID>

<Address>

<OrganisationFormattedName>C&L</OrganisationFormattedName>

(This is only a sample of the file)

This above file is fed through a mapping routine which changes the contents from SAP-XLM to PIDX format. This works fine and results in the following file format:

<ns2:PartnerName>C&L</ns2:PartnerName>

Now if I turn on my Java Map after the message map it give me the previous error with the file not completley transformed. I also noticed when testing the Java Mapping in netweaver Developer Studio that the streamTransformation seems to automatically convert the C%amp;L to C&L on my output without any coding from me.

henrique_pinto
Active Contributor
0 Kudos

If your XML file has UTF-8 encoding, try to use '&#38;' instead of just '&'.

Regards,

Henrique.

0 Kudos

Hello Netrouter (whatever that's supposed to signify),

It sounds like you are producing XML by simple String concatenation or something like that instead of using the Java API for XML Processing (JAXP). While this will get the job done in the simplest of cases, you must take great care with certain characters e.g. & and < in particular.

The best solution is to always use JAXP to parse and emit XML. More info can be found <a href="http://help.sap.com/saphelp_nw04/helpdata/en/34/e2343e8c7f6329e10000000a114084/content.htm">here</a>.

Regards,

Thorsten

bhavesh_kantilal
Active Contributor
0 Kudos

Hi,

Which Parser are you sisng? SAX or DOM?

In SAX , in the CHARS method, write the code to replace & with <b>&amp;</b> .

In DOM, do a serarch and replace.

The problem with & with also occure with

> - &gt;

< - &lt;

" - &quot;

' - &apos;

Regards,

Bhavesh

0 Kudos

Hi Bhavesh,

That is not correct. Using JAXP (SAX or DOM) you do <i>not</i> need to convert these characters yourself - the API takes care of it for you.

Regards,

Thorsten

bhavesh_kantilal
Active Contributor
0 Kudos

Hi Thorsten,

I agree partially. and I guess some explnantion is needed for my earlier statement.

When you call the prase method of the SAX parser , the input to the CHARS method will take & as such as & . <b>If you do not do a replace of & with &amp; in the chars method , an error will occur when the output stream is pushed out of the mapping program.</b>

And so, the output out of your JAVA Maping should have & as &amp; and so on.

Regards,

Bhavesh

0 Kudos

Hi Bhavesh,

Regarding "the output out of your JAVA Maping should have & as &amp; and so on", this is only true if you are pushing Strings directly to the output stream - something you <i>should not do</i>. Rather, you should wrap the output stream in a <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/xml/transform/stream/StreamResult.html">javax.xml.transform.stream.StreamResult</a> and use a <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/xml/transform/Transformer.html">javax.xml.transform.Tranformer</a> to emit the output to the StreamResult. Examples of transforming both SAX and DOM to stream can be found <a href="http://help.sap.com/saphelp_nw04/helpdata/en/5b/d4fb53ef5bac49b107a9b0ed90817f/frameset.htm">here</a>.

Regards,

Thorsten

bhavesh_kantilal
Active Contributor
0 Kudos

Hi Thorsten,

Thanks for that info. Will do the reading up and get back for clarifications , if any.

Regards,

Bhavesh