on 08-03-2006 9:13 PM
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?
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();
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Netrouter,
Can you post the erroring out part of ur XML here?
cheers,
Prashanth
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
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
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 & 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 & and so on.
Regards,
Bhavesh
Hi Bhavesh,
Regarding "the output out of your JAVA Maping should have & as & 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
User | Count |
---|---|
85 | |
10 | |
10 | |
10 | |
7 | |
6 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.