Issue in parsing xml using xPathAPI - java

I am trying to parse the following xml, but getting repeated first sub tag [] on each iteration instead of getting the values of next sub tags [i.e ]. Kindly provide your help.
<error_code_rules enabled="true">
<errors>
<error>
<error_source>ldap</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-1</oms_error_code>
<priority>3</priority>
</error>
<error>
<error_source>nagravision</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-2</oms_error_code>
<priority>1</priority>
</error>
<error>
<error_source>hitexpress</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-3</oms_error_code>
<priority>2</priority>
</error>
<error>
<error_source>netinventory</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-4</oms_error_code>
<priority>2</priority>
</error>
<error>
<error_source>seachangeeventis</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-5</oms_error_code>
<priority>2</priority>
</error>
<error>
<error_source>embratel</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-6</oms_error_code>
<priority>2</priority>
</error>
<error>
<error_source>siemens</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-7</oms_error_code>
<priority>2</priority>
</error>
<error>
<error_source>netsiemens</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-8</oms_error_code>
<priority>2</priority>
</error>
<error>
<error_source>nokiaonends</error_source>
<error_code>ALL</error_code>
<oms_error_code>OMS-9</oms_error_code>
<priority>2</priority>
</error>
</errors>
</error_code_rules>
The code for parsing the xml doc is as follows
private void populateKsuRulesList() {
logger.trace(3, "Populating ksuRulesList");
logger.log("populter ksu rule list");
CachedXPathAPI xPathAPI = new CachedXPathAPI();
try {
NodeList components = xPathAPI.eval(doc, KSU_RULES_COMPONENT_PATH)
.nodelist();
logger.log("components.getLength()" + components.getLength());
for (int i = 0; i < components.getLength(); i++) {
Node component = components.item(i);
// NodeIterator nodeItr = xPathAPI.selectNodeIterator(component,
// KSU_RULES_COMPONENT_CATEGORY_PATH);
String componentCategory = xPathAPI.eval(components.item(i),
KSU_RULES_COMPONENT_CATEGORY_PATH).toString();
String componentType = xPathAPI.eval(component,
KSU_RULES_COMPONENT_TYPE_PATH).toString();
String mandatory = xPathAPI.eval(component,
KSU_RULES_MANDATORY_PATH).toString();
logger.log("componentCategory" + componentCategory);
logger.log("componentType" + componentType);
logger.log("mandatory" + mandatory);
String ruleParms[] = { componentCategory, componentType,
mandatory };
ksuRulesList.add(ruleParms);
}
} catch (TransformerException te) {
logger.log("Exception: ", te);
}
}

Try this one .
NodeList components = xPathAPI.eval(doc, "//errors/error").nodelist();
System.out.println("components.getLength()" + components.getLength());
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
for (int i = 0; i < components.getLength(); i++) {
Node component = components.item(i);
Element product = (Element) component;
NodeList nodes = (NodeList) xpath.compile("error_source").evaluate(product, XPathConstants.NODESET);
System.out.println(nodes.item(0).getTextContent());
}

Related

Extract values for more than one attribute node values via XPath expression

How can I extract value of more than one attribute node via XPath expression?
A sample XML file is:
<tag1>
<tag2>
<tag3 id="1">
<tage4>
<tage4code code="1">
<tag5>
<tage4Value Day="14" Month="Oct" Year="2000" />
</tag5>
<tag5>
<tage4Value Month="Oct" Year="2001" />
</tag5>
<tag5>
<tage4Value Year="2002" />
</tag5>
<tag5>
<tage4Value Day="1" Month="Jan" Year="1999" />
</tag5>
<tag5>
<tage4Value Year="1940" />
</tag5>
</tage4code>
</tage4>
</tag3>
</tag2>
</tag1>
So far I have this XPath string:
XPathExpression expr = xpath.compile("concat((/tag1/tag2/tag3[#id=1]/tage4/tage4code[#code=1]/tag5/tage4Value/#Day, '/' , /tag1/tag2/tag3[#id=1]/tage4/tage4code[#code=1]/tag5/tage4Value/#Month, '/', /tag1/tag2/tag3[#id=1]/tage4/tage4code[#code=1]/tag5/tage4Value/#Year)");
NodeList combination1 = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int a = 0; a <= combination1.getLength(); a++) {
System.out.println("date : " + combination.item(a).getNodeValue());
}
My Expected result
14/Oct/2000
Oct/2001
2002
1/Jan/1999
1940
Can someone help to correct my XPathExpression
XPath 2.0 solution :
tokenize(replace(replace(replace(substring-after(string-join(//tag5/*|//tag5//#*,","),","),",,","%"),","," ")," ","/"),"%")
Output :
String='14/Oct/2000'
String='Oct/2001'
String='2002'
String='1/Jan/1999'
String='1940'
XPath 1.0 solution :
concat(translate(normalize-space(concat((//tage4Value)[1]/#Day," ",(//tage4Value)[1]/#Month," ",(//tage4Value)[1]/#Year))," ","/"),"|",translate(normalize-space(concat((//tage4Value)[2]/#Day," ",(//tage4Value)[2]/#Month," ",(//tage4Value)[2]/#Year))," ","/"),"|",translate(normalize-space(concat((//tage4Value)[3]/#Day," ",(//tage4Value)[3]/#Month," ",(//tage4Value)[3]/#Year))," ","/"),"|",translate(normalize-space(concat((//tage4Value)[4]/#Day," ",(//tage4Value)[4]/#Month," ",(//tage4Value)[4]/#Year))," ","/"),"|",translate(normalize-space(concat((//tage4Value)[5]/#Day," ",(//tage4Value)[5]/#Month," ",(//tage4Value)[5]/#Year))," ","/"))
Output :
String='14/Oct/2000|Oct/2001|2002|1/Jan/1999|1940'
Or with new line separator :
concat(translate(normalize-space(concat((//tage4Value)[1]/#Day," ",(//tage4Value)[1]/#Month," ",(//tage4Value)[1]/#Year))," ","/"),codepoints-to-string(10),translate(normalize-space(concat((//tage4Value)[2]/#Day," ",(//tage4Value)[2]/#Month," ",(//tage4Value)[2]/#Year))," ","/"),codepoints-to-string(10),translate(normalize-space(concat((//tage4Value)[3]/#Day," ",(//tage4Value)[3]/#Month," ",(//tage4Value)[3]/#Year))," ","/"),codepoints-to-string(10),translate(normalize-space(concat((//tage4Value)[4]/#Day," ",(//tage4Value)[4]/#Month," ",(//tage4Value)[4]/#Year))," ","/"),codepoints-to-string(10),translate(normalize-space(concat((//tage4Value)[5]/#Day," ",(//tage4Value)[5]/#Month," ",(//tage4Value)[5]/#Year))," ","/"))
Output :
String='14/Oct/2000
Oct/2001
2002
1/Jan/1999
1940'
This xpath expression
//tag3[#id="1"]//tage4code[#code=1]//tag5/tage4Value/concat(#Day,'/',#Month,'/',#Year)
should output
14/Oct/2000
/Oct/2001
//2002
1/Jan/1999
//1940
This way we can create a dynamic way of reading the child.
xpathExpression = "count(//tag1/tag2/tag3[#id=1]/tage4/tage4code[#code=1]/tag5/tage4Value)";
double nodeList1 = (double) xpath.compile(xpathExpression).evaluate(doc, XPathConstants.NUMBER);
int s = (int) (nodeList1);
for (int z = 1; z <= s; z++) {
xpathExpression = "normalize-space(concat((//tag1/tag2/tag3[#id=1]/tage4/tage4code[#code=1]/tag5/tage4Value)["
+ z
+ "]/#Day,\" \",(//tag1/tag2/tag3[#id=1]/tage4/tage4code[#code=1]/tag5/tage4Value)["
+ z
+ "]/#Month,\" \",(//tag1/tag2/tag3[#id=1]/tage4/tage4code[#code=1]/tag5/tage4Value)["
+ z + "]/#Year))";
String year = (String) xpath.evaluate(xpathExpression, doc, XPathConstants.STRING);
System.out.println(year);
}

Split unsymmetrical XML into multiple XMLs

I have to split an unsymmetrical xml on 'Trade' element using java
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<BookingRequest>
<Id>1234</Id>
<App>Pan</App>
<Parties>
<Party>1</Party>
<Party>2</Party>
</Parties>
<Contract>
<Trades>
<Trade>
<Detail>100</Detail>
<Location>
<Num>10001</Num>
</Location>
</Trade>
<Trade>
<Detail>101</Detail>
<Location>
<Num>10002</Num>
</Location>
</Trade>
</Trades>
</Contract>
</BookingRequest>
My requirement is post split there should be 2 files:
FILE 1:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<BookingRequest>
<Id>1234</Id>
<App>Pan</App>
<Parties>
<Party>1</Party>
<Party>2</Party>
</Parties>
<Contract>
<Trades>
<Trade>
<Detail>100</Detail>
<Location>
<Num>10001</Num>
</Location>
</Trade>
</Trades>
</Contract>
</BookingRequest>
FILE 2:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<BookingRequest>
<Id>1234</Id>
<App>Pan</App>
<Parties>
<Party>1</Party>
<Party>2</Party>
</Parties>
<Contract>
<Trades>
<Trade>
<Detail>101</Detail>
<Location>
<Num>10002</Num>
</Location>
</Trade>
</Trades>
</Contract>
</BookingRequest>
Could someone help me in doing this kind of splitting (preferably using DOM/XPath and NOT XSLT)
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().parse("booking-request.xml");
Element bookingRequest = doc.getDocumentElement();
Element contract = (Element)bookingRequest.getElementsByTagName("Contract").item(0);
Element trades = (Element)contract.getElementsByTagName("Trades").item(0);
List<Element> tradeList = new ArrayList<Element>();
NodeList nodeList = trades.getElementsByTagName("Trade");
for(int i=0; i<nodeList.getLength(); i++)
tradeList.add((Element)nodeList.item(i));
Transformer transformer = TransformerFactory.newInstance().newTransformer();
int i = 0;
for(Element trade: tradeList){
// remove all children of <Trades>
while(trades.getFirstChild()!=null)
trades.removeChild(trades.getFirstChild());
trades.appendChild(doc.createTextNode("\n "));
trades.appendChild(trade);
trades.appendChild(doc.createTextNode("\n "));
++i;
transformer.transform(new DOMSource(doc), new StreamResult(new File("trade"+i+".xml")));
}

How to parse unconventional XML files

I have the need to take what I consider an "unconventional" XML file that I get in and convert it into what I consider "conventional". The below XML examples have been "scrubbed" of proprietary names/values.
Here is what the "unconventional" XML file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<dataView name="document/aDocument" xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dataItems>
<dataItem name="item1" location="item1" dataItemType="Long">
<value xsi:type="xs:string">1</value>
</dataItem>
<dataItem name="item2" location="item.seconditem(some item).ref" dataItemType="String">
<value xsi:type="xs:string">ABC2DEF3</value>
</dataItem>
</dataItems>
<dataRepeaters>
<dataRepeater name="SomeLevel1" runtimeInfomration="SomeLevel11984371030">
<dataGroups>
<dataGroup name="SomeLevel2" location="SomeLevel:(a level).thelevel" keyValue="SomeLevel119843710300" runtimeInformation="19843710300">
<dataItems>
<dataItem name="someItem1" location="someLevel.aLevel(another item)" dataItemType="String">
<value xsi:type="xs:string">12345</value>
</dataItem>
<dataItem name="someItem2" location="someLevel.aLevel(another item2)" dataItemType="Integer"/>
<dataItem name="someItem3" location="someLevel.aLevel(another item3)" dataItemType="ObjectReference">
<value xsi:type="xs:string">11:20012:3536</value>
</dataItem>
<dataItem name="someItem4" location="someLevel.aLevel(another item4)" dataItemType="String"/>
<dataItem name="someItem5" location="someLevel.aLevel(another item5)" dataItemType="String">
<value xsi:type="xs:string">someItem5 Data</value>
</dataItem>
<dataItem name="someItem6" location="someLevel.aLevel(another item6)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">123456:USD</value>
</dataItem>
</dataItems>
</dataGroup>
<dataGroup name="SomeLevel3" keyValue="SomeLevel31984371030" runtimeInformation="1984371030">
<dataRepeaters>
<dataRepeater name="SomeLevel4" runtimeInfomration="SomeLevel4">
<dataGroups>
<dataGroup name="SomeLevel5" location="anotherLevel.level5(SomeLevel5):someLevel5" keyValue="SomeLevel51984371030-11521863690" runtimeInformation="1984371030-11521863690">
<dataItems>
<dataItem name="someItem6" location="someLevel.aLevel(another item6)" dataItemType="BigDecimal">
<value xsi:type="xs:string">303.149</value>
</dataItem>
<dataItem name="someItem7" location="someLevel.aLevel(another item7)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">117:USD</value>
</dataItem>
<dataItem name="someItem8" location="someLevel.aLevel(another item8)" dataItemType="String">
<value xsi:type="xs:string">117.000000:USD</value>
</dataItem>
<dataItem name="someItem9" location="someLevel.aLevel(another item9)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">117:USD</value>
</dataItem>
</dataItems>
<dataRepeaters>
<dataRepeater name="SomeLevel6" runtimeInfomration="someLevel6">
<dataGroups/>
</dataRepeater>
</dataRepeaters>
</dataGroup>
<dataGroup name="SomeLevel7" location="anotherLevel.level5(SomeLevel7):someLevel7" keyValue="SomeLevel71984371030-11521863690" runtimeInformation="1984371030-11521863690">
<dataItems>
<dataItem name="someItem10" location="someLevel.aLevel(another item10)" dataItemType="BigDecimal">
<value xsi:type="xs:string">292.741</value>
</dataItem>
<dataItem name="someItem11" location="someLevel.aLevel(another item11)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">165:USD</value>
</dataItem>
<dataItem name="someItem12" location="someLevel.aLevel(another item12)" dataItemType="String">
<value xsi:type="xs:string">165.000000:USD</value>
</dataItem>
<dataItem name="someItem13" location="someLevel.aLevel(another item13)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">165:USD</value>
</dataItem>
</dataItems>
<dataRepeaters/>
</dataGroup>
<dataGroup name="SomeLevel8" location="anotherLevel.level5(SomeLevel8):someLevel8" keyValue="SomeLevel81984371030-11521863690" runtimeInformation="1984371030-11521863690">
<dataItems>
<dataItem name="someItem14" location="someLevel.aLevel(another item14)" dataItemType="BigDecimal">
<value xsi:type="xs:string">369.075</value>
</dataItem>
<dataItem name="someItem15" location="someLevel.aLevel(another item15)" dataItemType="CurrencyAmount">
<value xsi:type="xs:string">598:USD</value>
</dataItem>
<dataItem name="someItem16" location="someLevel.aLevel(another item16)" dataItemType="String">
<value xsi:type="xs:string">598.000000:USD</value>
</dataItem>
</dataItems>
<dataRepeaters>
<dataRepeater name="SomeLevel9" runtimeInfomration="someLevel9">
<dataGroups>
<dataGroup name="SomeLevel10" location="ownedAuto.AgreementActual(Liability).ConstantRole(Policy Form):policyForm" keyValue="aomeLevel101984371030-11521863690-115218636900" runtimeInformation="1984371030-11521863690-115218636900">
<dataItems>
<dataItem name="someItem17" location="someLevel.aLevel(another item17)" dataItemType="String">
<value xsi:type="xs:string">Some Data | ABC 123</value>
</dataItem>
<dataItem name="someItem18" location="someLevel.aLevel(another item18)" dataItemType="Integer">
<value xsi:type="xs:string">2</value>
</dataItem>
</dataItems>
</dataGroup>
</dataGroups>
</dataRepeater>
<dataRepeater name="SomeLevel10" runtimeInfomration="someLevel11">
<dataGroups/>
</dataRepeater>
</dataRepeaters>
</dataGroup>
</dataGroups>
</dataRepeater>
</dataRepeaters>
</dataGroup>
</dataGroups>
</dataRepeater>
</dataRepeaters>
</dataView>
I am trying to convert it to something like this:
<?xml version="1.0" encoding="UTF-8"?>
<dataView name="document/aDocument" xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item1>1</item1>
<item2>ABC2DEF3</item2>
<SomeLevel1>
<SomeLevel2>
<someItem1>12345f</someItem1>
<someItem2></someItem2>
<someItem3>11:20012:3536</someItem3>
<someItem4>12345f</someItem4>
<someItem5>someItem5 Data</someItem5>
<someItem6>123456:USD</someItem6>
</SomeLevel2>
<SomeLevel3>
<SomeLevel4>
<SomeLevel5>
<someItem7>303.149</someItem7>
<someItem8>117:USD</someItem8>
<someItem9>117.000000:USD</someItem9>
<someItem10>117:USD</someItem10>
<SomeLevel6></SomeLevel6>
</SomeLevel5>
<SomeLevel7>
<someItem11>292.741</someItem11>
<someItem12>165:USD</someItem12>
<someItem13>165.000000:USD</someItem13>
<someItem14>165:USD</someItem14>
</SomeLevel7>
<SomeLevel8>
<someItem15>369.075</someItem15>
<someItem16>598:USD</someItem16>
<someItem17>598.000000:USD</someItem17>
<SomeLevel9>
<SomeLevel10>
<someItem18>Some Data | ABC 123</someItem18>
<someItem19>2</someItem19>
</SomeLevel10>
</SomeLevel9>
<SomeLevel11></SomeLevel11>
</SomeLevel8>
</SomeLevel4>
</SomeLevel3>
</SomeLevel1>
</dataView>
So basically I am trying to take the "name" attribute and make it the XML node/tag and the value between the <value> node/tag and use it as the "value" for the XML node/tag.
I have tried several different parsing/writing "routines" and the below two are the two that have gotten me the closest. So I'm leaving out the other ones as they would be just "noise".
Here is what I have tried so far:
private Document xmlDocument;
public void convertXML() {
xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader("DSExample.xml")));
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Node dsNode = xmlDocument.getDocumentElement();
xmlDocument = docBuilder.newDocument();
// Attempt 1:
doSomethingDS(dsNode); // This will convert the XML but with NO nesting - creates example output 1
// Attempt 2:
traverseDS(dsNode); // This will create an XML with ONLY the root dataItems - Don't know why - creates example output 2
}
public void doSomethingDS(Node node) {
System.out.println(node.getNodeName());
Element xmlElement = null;
// This will be the "root" element/node "dataView":
if(node.getNodeName() != null && node.getNodeName().equalsIgnoreCase("dataView")) {
// Debugging: Print the node
printNode(node);
String nodeName = node.getNodeName().trim();
rootElement = xmlDocument.createElement(nodeName);
mPreviousElement = rootElement;
addAllAttributesToRootElement((Element) node, rootElement);
xmlDocument.appendChild(rootElement);
}
else {
// Debugging: Print the node
printNode(node);
// If has "name" property - create element/node
if(node.getAttributes() != null && node.getAttributes().getNamedItem("name") != null) {
xmlElement = createElement(xmlDocument, node);
if(xmlElement !=null && xmlDocument.getFirstChild() != null) {
xmlDocument.getFirstChild().appendChild(xmlElement);
}
}
}
NodeList nodeList = node.getChildNodes();
for(int i = 0; i < nodeList.getLength(); i++) {
Node currentNode = nodeList.item(i);
if(currentNode.getNodeType() == Node.ELEMENT_NODE) {
// recursively call this method for all the children which are of type Element
doSomethingDS(currentNode);
}
}
} // End of doSomethingDS()
public void traverseDS(Node parentNode) {
// This will create an XML with ONLY the root dataItems - Don't know why.
Element xmlElement = null;
//****************************************************************
// This will be the "root" element/node "dataView":
if(parentNode.getNodeName() != null && parentNode.getNodeName().equalsIgnoreCase("dataView")) {
// Debugging: Print the node
printNode(parentNode);
String nodeName = parentNode.getNodeName().trim();
rootElement = xmlDocument.createElement(nodeName);
mPreviousElement = rootElement;
if(!isRootNodeSet) {
mRootNode = parentNode;
isRootNodeSet = true;
}
addAllAttributesToRootElement((Element) parentNode, rootElement);
xmlDocument.appendChild(rootElement);
// traverse children
Node theNode = parentNode.getFirstChild();
if(theNode != null) {
theNode = theNode.getNextSibling();
}
else if (isRootNodeSet) {
theNode = mRootNode.getNextSibling();
}
traverseDS(theNode);
}
else {
// traverse all nodes that belong to the parent
for(Node theNode = parentNode.getFirstChild(); theNode != null; theNode = theNode.getNextSibling()) {
// Debugging: Print the node
printNode(theNode);
// If has "name" property - create element/node
if(theNode.getAttributes() != null && theNode.getAttributes().getNamedItem("name") != null) {
// Create new Element/Node
xmlElement = createElement(xmlDocument, theNode);
if(xmlElement !=null && xmlDocument.getFirstChild() != null) {
xmlDocument.getFirstChild().appendChild(xmlElement);
}
else {
System.out.println(" not a node we wanted?");
}
}
// traverse children
traverseDS(theNode);
}
}
} // End of traverseDS()
private Element createElement(Document aDoc, Node aNode) {
Element xmlElement = null;
String elementName = "";
NamedNodeMap dataNodeMap = aNode.getAttributes();
if(dataNodeMap != null && dataNodeMap.getNamedItem("name") != null) {
elementName = dataNodeMap.getNamedItem("name").getTextContent();
xmlElement = aDoc.createElement(elementName);
// if node = "dataItem" - walk node to get <value> node
// Note: some "dataItem" nodes also have a <previousValue> node - what to do with these????
if(aNode.getNodeName() != null && aNode.getNodeName().equalsIgnoreCase("dataItem")) {
// Walk Node to get <value> node
NodeList childNodes = aNode.getChildNodes();
int childNodesLength = childNodes.getLength();
for(int x = 0; x < childNodesLength; x++) {
Node childNode = childNodes.item(x);
if(childNode.getNodeName() != null && childNode.getNodeName().equalsIgnoreCase("value")) {
xmlElement.setTextContent(childNode.getTextContent());
break;
}
}
}
}
return xmlElement;
} // End of createElement()
Example Output 1 (created by doSomethingDS()):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<dataView xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="document/aDocument">
<item1>1</item1>
<item2>ABC2DEF3</item2>
<SomeLevel1/>
<SomeLevel2/>
<someItem1>12345</someItem1>
<someItem2/>
<someItem3>11:20012:3536</someItem3>
<someItem4/>
<someItem5>someItem5 Data</someItem5>
<someItem6>123456:USD</someItem6>
<SomeLevel3/>
<SomeLevel4/>
<SomeLevel5/>
<someItem6>303.149</someItem6>
<someItem7>117:USD</someItem7>
<someItem8>117.000000:USD</someItem8>
<someItem9>117:USD</someItem9>
<SomeLevel6/>
<SomeLevel7/>
<someItem10>292.741</someItem10>
<someItem11>165:USD</someItem11>
<someItem12>165.000000:USD</someItem12>
<someItem13>165:USD</someItem13>
<SomeLevel8/>
<someItem14>369.075</someItem14>
<someItem15>598:USD</someItem15>
<someItem16>598.000000:USD</someItem16>
<SomeLevel9/>
<SomeLevel10/>
<someItem17>Some Data | ABC 123</someItem17>
<someItem18>2</someItem18>
<SomeLevel11/>
</dataView>
Example Output 2 (Created by traverseDS()):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<dataView xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="document/aDocument">
<item1>1</item1>
<item2>ABC2DEF3</item2>
</dataView>
Now here is that catch.... What I get is dynamic I could get a Mac truck one time and a Toyota the next or a mixture of the two. And the size of the XML I get could be small or large. So it's hard to just use XPath or directly go after specific elements as I don't know what I'll get. This is why I'm basically walking/traversing the DOM a node at a time to extract out just what is useable.
So my question is:
What am I doing wrong in my parsing/writing of the XML file to not get it to look like what I'm trying to get it to look like?
This is (almost) trivially easy with XSLT:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ds="http://component.mycompany.com/entity/ds"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://component.mycompany.com/entity/ds"
>
<xsl:output indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="ds:dataView" priority="1">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="ds:*[#name]">
<xsl:element name="{#name}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="normalize-space()" />
</xsl:template>
</xsl:stylesheet>
applied do your input, gives you:
<dataView xmlns="http://component.mycompany.com/entity/ds" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item1>1</item1>
<item2>ABC2DEF3</item2>
<SomeLevel1>
<SomeLevel2>
<someItem1>12345</someItem1>
<someItem2 />
<someItem3>11:20012:3536</someItem3>
<someItem4 />
<someItem5>someItem5 Data</someItem5>
<someItem6>123456:USD</someItem6>
</SomeLevel2>
<SomeLevel3>
<SomeLevel4>
<SomeLevel5>
<someItem6>303.149</someItem6>
<someItem7>117:USD</someItem7>
<someItem8>117.000000:USD</someItem8>
<someItem9>117:USD</someItem9>
<SomeLevel6 />
</SomeLevel5>
<SomeLevel7>
<someItem10>292.741</someItem10>
<someItem11>165:USD</someItem11>
<someItem12>165.000000:USD</someItem12>
<someItem13>165:USD</someItem13>
</SomeLevel7>
<SomeLevel8>
<someItem14>369.075</someItem14>
<someItem15>598:USD</someItem15>
<someItem16>598.000000:USD</someItem16>
<SomeLevel9>
<SomeLevel10>
<someItem17>Some Data | ABC 123</someItem17>
<someItem18>2</someItem18>
</SomeLevel10>
</SomeLevel9>
<SomeLevel10 />
</SomeLevel8>
</SomeLevel4>
</SomeLevel3>
</SomeLevel1>
</dataView>
Notes:
Having numbered element names (someItem1 thru someItem6) will come back and bite you, eventually. XML elements have a natural order (or you can have a "number" attribute), putting a counter into the name is bad and wrong. Take my advice and don't do that (*).
To understand the solution here's a quick breakdown:
XSLT processors run XML nodes through templates by finding the best match for the XML node at hand.
The process starts with the root node.
Since there is no template explicitly matching the root node (<xsl:template match="/">), a default rule kicks in: Output nothing, but find templates for the child nodes.
The first (and only) child node is the document element (<ds:dataView>).
The template #1 matches that node, tells the processor to copy it and process its children (<xsl:apply-templates />).
Every element that has a #name is matched by template #2, which outputs an element with that name and again processes its children.
Every other element (like those <value> nodes) is - in the absence of any matching template - processed according to the mentioned default rule.
Text nodes are matched by template #3, which outputs their trimmed value.
Additional notes:
The expression in curly braces is called an attribute value template.
The template priority="1" makes sure that this template is selected for the <ds:dataView> element, because the other one would match as well.
Your result document still is in the "http://component.mycompany.com/entity/ds". This might or might not be correct. I suspect it's not correct, technically speaking, but you decide.
(*) <xsl:element name="{translate(#name, '0123456789', '')}" would be one variant to lose the counters.
XSLT has been created exactly for a task like that. As long as your Source-XML (unconventional xml) is well-formed (correct xml-syntax) so that it can be read by a standard xml-parser like DOM, you can use that.
It works like so: You create a xsl-template file that contains a declerative description how the source xml should be transformed into another format. The transformation itself is done by a XSL-Transformer.
The xsl is also an xml-format, so it should be quit easy readable, as long as the transformation is not too complex.
Here is explained how that can be implemented:
http://docs.oracle.com/javase/tutorial/jaxp/xslt/transformingXML.html

NullPointerException when importing XML-file into Processing, Java

I'm trying to get data from an XML-file and use this data in processing. When doing so I get a NPE, and I can't quite figure out where I'm wrong. The XML got several layers and I have to get data from this "child":
http://i62.tinypic.com/2mb90g.png
My code looks like this:
XML xml;
void setup(){
xml = loadXML("parker.xml");
XML[] children = xml.getChildren("kml");
XML[] Folder=children[0].getChildren("Folder");
XML[] Placemark=Folder[1].getChildren("Placemark");
XML[] Polygon=Placemark[2].getChildren("Polygon");
XML[] outerBoundaryIs=Polygon[3].getChildren("outerBoundaryIs");
XML[] LinearRing=outerBoundaryIs[4].getChildren("LinearRing");
for (int i = 0; i < LinearRing.length; i++) {
float coordinates = children[i].getFloat("coordinates");
println(coordinates);
}
}
Best Chris
Stack trace:
[Fatal Error] :1:1: Content is not allowed in prolog.
org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content
is not allowed in prolog. at
com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:257)
at
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)
at processing.data.XML.(XML.java:187) at
processing.core.PApplet.loadXML(PApplet.java:6310) at
processing.core.PApplet.loadXML(PApplet.java:6300) at
XMLtryout.setup(XMLtryout.java:21) at
processing.core.PApplet.handleDraw(PApplet.java:2359) at
processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
at processing.core.PApplet.run(PApplet.java:2254) at
java.lang.Thread.run(Thread.java:744)
XML file:
https://www.dropbox.com/s/xn3thjskhlf2wai/parker.xml
This error maybe caused because missing this at the top of your xml file
<?xml version="1.0" encoding="utf-8"?>
or there's some non-printable garbage at the start of your file.
The 'Content is not allowed in prolog' error indicates that you have some content between the XML declaration and the appearance of the document element, for example
<?xml version="1.0" encoding="utf-8"?>
content here is not allowed
<kml xmlns="http://earth.google.com/kml/2.1">
...
</kml>
The XML file you linked is ok though, so it seems you're
reading the XML binary incorrectly before passing it to the XML parser,
or (more likely) you're not reading the XML at all (can happen when you read from a web URL and getting an error response). I assume you get a HTTP 40x error which you don't recognize, and read the response (usually HTML) as XML, which causes the error. Remember that applets usually can only read resources from the same server (that's what might cause the error).
To verify this, attempt to read the URL content and output it as text, and check if it looks ok.
Make it more easy
try like this
public static void setUp(){
try {
File file = new File("parker.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
doc.getDocumentElement().normalize();
System.out.println("Root element " + doc.getDocumentElement().getNodeName());
NodeList nodeLst = doc.getElementsByTagName("LinearRing");
System.out.println("Information");
for (int s = 0; s < nodeLst.getLength(); s++) {
Node fstNode = nodeLst.item(s);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElmnt = (Element) fstNode;
NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("coordinates");
Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
NodeList fstNm = fstNmElmnt.getChildNodes();
System.out.println("coordinates : " + ((Node) fstNm.item(0)).getNodeValue());
//
//
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
that should display :
Root element kml
Information
coordinates :
10.088512,56.154109,0
10.088512,56.154109,0
10.088512,56.154109,0
10.088511,56.15411,0
10.088511,56.15411,0
10.08851,56.15411,0
10.08851,56.154111,0
10.088509,56.154111,0
10.088508,56.154111,0
10.088508,56.154111,0
10.088507,56.154111,0
10.088506,56.154111,0
10.088506,56.154111,0
10.088505,56.154111,0
10.088504,56.154111,0
10.088504,56.154111,0
10.088503,56.15411,0
10.088503,56.15411,0
10.088502,56.15411,0
10.088502,56.154109,0
10.088502,56.154109,0
10.088501,56.154109,0
10.088501,56.154108,0
10.088501,56.154108,0
10.088501,56.154108,0
10.088501,56.154107,0
10.088285,56.154094,0
10.088104,56.154372,0
10.088061,56.154401,0
10.087988,56.15445,0
10.087915,56.154611,0
10.08791,56.154613,0
10.087912,56.154613,0
10.087877,56.1548,0
10.08772,56.15482,0
10.087558,56.154911,0
10.087421,56.155111,0
10.087316,56.155308,0
10.087328,56.15538,0
10.087372,56.155413,0
10.087446,56.155453,0
10.087484,56.155487,0
10.08747,56.155601,0
10.08772,56.155616,0
10.087719,56.155618,0
10.088618,56.155671,0
10.089096,56.1557,0
10.089096,56.155699,0
10.089138,56.155701,0
10.089127,56.155706,0
10.089004,56.155787,0
10.08888,56.155853,0
10.088799,56.155806,0
10.088571,56.155914,0
10.088455,56.155946,0
10.088112,56.156081,0
10.088184,56.156138,0
10.087733,56.156353,0
10.087489,56.156421,0
10.087288,56.156341,0
10.087268,56.156333,0
10.086893,56.156182,0
10.08684,56.156271,0
10.087049,56.156373,0
10.086893,56.156455,0
10.086664,56.156575,0
10.086443,56.156698,0
10.086425,56.156708,0
10.085983,56.156955,0
10.085655,56.157139,0
10.085462,56.157276,0
10.085272,56.157233,0
10.085176,56.157328,0
10.084917,56.157393,0
10.084883,56.157458,0
10.08495,56.157513,0
10.084947,56.157524,0
10.084943,56.157539,0
10.084855,56.15787,0
10.084855,56.15787,0
10.084321,56.157317,0
10.085553,56.156195,0
10.085555,56.156194,0
10.085553,56.156194,0
10.085734,56.156035,0
10.085821,56.155977,0
10.085937,56.155932,0
10.085993,56.155942,0
10.086031,56.155959,0
10.086171,56.15592,0
10.086227,56.155901,0
10.086392,56.155841,0
10.086513,56.155786,0
10.08664,56.155699,0
10.086686,56.155657,0
10.086727,56.155605,0
10.086777,56.155486,0
10.086861,56.155289,0
10.086916,56.155134,0
10.087006,56.154899,0
10.087075,56.154706,0
10.087094,56.154649,0
10.0871,56.154574,0
10.087112,56.154464,0
10.087111,56.154362,0
10.087112,56.154279,0
10.087112,56.154279,0
10.087113,56.15427,0
10.087114,56.154198,0
10.087108,56.15413,0
10.087091,56.154054,0
10.086992,56.153698,0
10.087,56.153678,0
10.087031,56.153647,0
10.087036,56.153648,0
10.087046,56.153652,0
10.087035,56.153647,0
10.087039,56.153645,0
10.087072,56.153612,0
10.087367,56.153308,0
10.087371,56.153303,0
10.08742,56.15323,0
10.087568,56.152963,0
10.087568,56.152962,0
10.087569,56.152962,0
10.08757,56.152961,0
10.087571,56.15296,0
10.087573,56.152959,0
10.087574,56.152959,0
10.087575,56.152958,0
10.087577,56.152958,0
10.087579,56.152958,0
10.087581,56.152957,0
10.087582,56.152957,0
10.087584,56.152957,0
10.087586,56.152958,0
10.087588,56.152958,0
10.087589,56.152958,0
10.087591,56.152959,0
10.087592,56.152959,0
10.087593,56.15296,0
10.087594,56.152961,0
10.087595,56.152962,0
10.087596,56.152963,0
10.087596,56.152964,0
10.087596,56.152965,0
10.087596,56.152965,0
10.087614,56.152967,0
10.087921,56.152988,0
10.088134,56.153019,0
10.088311,56.15304,0
10.088454,56.153052,0
10.088469,56.153378,0
10.08847,56.153445,0
10.088473,56.153597,0
10.088473,56.153597,0
10.088473,56.153597,0
10.088703,56.153614,0
10.088703,56.153614,0
10.088703,56.153614,0
10.088704,56.153614,0
10.088705,56.153614,0
10.088705,56.153615,0
10.088706,56.153615,0
10.088706,56.153615,0
10.088707,56.153616,0
10.088707,56.153616,0
10.088707,56.153616,0
10.088707,56.153617,0
10.088707,56.153617,0
10.088707,56.153617,0
10.088707,56.153618,0
10.088512,56.154108,0
10.088512,56.154109,0
coordinates :
10.086779,56.155487,0
10.086778,56.155488,0
10.086779,56.155487,0
10.086779,56.155487,0
coordinates :
10.08847,56.153602,0
10.088469,56.153602,0
10.088469,56.153602,0
10.08847,56.153602,0
PS : kml is the root element

Xpath functionality

I have one module which consumes a webservice and fetches a response from it. The response which I am getting contains a value inside it on which I need to set it value. I am using XPath for that. Now when I am running this functionality on my local system I am getting the desired output, but when I am using that in my ear, it's not working.
The code in ear:
private static String stResponsePath="//Envelope//Body//AddNoteResponse//Response//";
private static String Fault_Path="//Envelope/Body/Fault/detail/CSIApplicationException/ServiceProviderEntity/";
/**
* Construct AddNoteResponse bean from
*
* #param addNote response SOAP XML
*/
public AddNoteResponse createAddNoteResponseFromSoapString(String soapString)throws EDDSystemException
{
try
{
Document soapDocument =AddNoteDomParserHelper.convertStringToDoc(soapString);
// EDDLog.outLog.info("soapDocument " + soapDocument.getFirstChild());
// EDDLog.outLog.info("soapDocument " + soapDocument.getLastChild());
EDDLog.outLog.info("soapString :" +soapString );
AddNoteResponse addNoteResponse= new AddNoteResponse();
addNoteResponse.setCode(AddNoteDomParserHelper.**getElementValue**(stResponsePath + "code", soapDocument));
addNoteResponse.setDescription(AddNoteDomParserHelper.**getElementValue**(stResponsePath + "description", soapDocument));
} .....
.....
}
public static String **getElementValue**(String elementName, Document doc) throws Exception
{
String value = "";
XPath xPath = XPathFactory.newInstance().newXPath();
if(xPath ==null)
{
EDDLog.outLog.info(" xpath is null");
}
EDDLog.outLog.info("doc " + doc.getFirstChild());
NodeList docNodes = (NodeList) xPath.evaluate(elementName,doc, XPathConstants.NODESET);
// NodeList docNodes = (NodeList) xPath.evaluate("/Envelope/Body/AddNoteResponse/Response/code",doc, XPathConstants.NODESET);
EDDLog.outLog.info("elementName :" +elementName );
//NodeList docNodes = doc.getElementsByTagNameNS("*", elementName);
if (docNodes == null || docNodes.getLength() == 0) {
docNodes = doc.getElementsByTagName(elementName);
EDDLog.outLog.info("docNodes.getLength() :"+docNodes.getLength());
}
Output of this is:
11 Jun 2013 13:47:40,644 INFO soapString :<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header> <MessageHeader xmlns:cng="http://csi.cingular.com/CSI/Nam
espaces/Types/Public/CingularDataModel.xsd" xmlns="http://csi.cingular.com/CSI/Namespaces/Types/Public/MessageHeader.xsd"><TrackingMessageHeader><cng:version>v68</cng:version><cng:originalVersion>v
68</cng:originalVersion><cng:messageId>46178</cng:messageId><cng:timeToLive>120000</cng:timeToLive><cng:conversationId>EDD~CNG-CSI~5bfa2f5f-103d-4056-b775-cb2028357a5c</cng:conversationId><cng:date
TimeStamp>2013-06-08T12:44:18.418Z</cng:dateTimeStamp><cng:uniqueTransactionId>ServiceGateway19121#q25csg1c1_4f771d65-41de-4c40-b4cc-0be179d3677c</cng:uniqueTransactionId></TrackingMessageHeader><S
ecurityMessageHeader><cng:userName>EDD</cng:userName><cng:userPassword>EDDtest</cng:userPassword></SecurityMessageHeader><SequenceMessageHeader><cng:sequenceNumber>1</cng:sequenceNumber><cng:totalInSequence>1</cng:totalInSequence></SequenceMessageHeader></MessageHeader></SOAP-ENV:Header> <SOAP-ENV:Body> <AddNoteResponse xmlns:cng="http://csi.cingular.com/CSI/Namespaces/Types/Public/CingularDataModel.xsd" xmlns="http://csi.cingular.com/CSI/Namespaces/Container/Public/AddNoteResponse.xsd"><Response><cng:code>0</cng:code><cng:description>Success</cng:description></Response></AddNoteResponse></SOAP-ENV:Body> </SOAP-ENV:Envelope>
11 Jun 2013 13:47:42,028 INFO doc [SOAP-ENV:Envelope: null]
11 Jun 2013 13:47:44,236 INFO elementName ://Envelope//Body//AddNoteResponse//Response//code
11 Jun 2013 13:47:44,236 INFO docNodes.getLength() :0
11 Jun 2013 13:47:44,243 INFO doc [SOAP-ENV:Envelope: null]
11 Jun 2013 13:47:44,254 INFO elementName ://Envelope//Body//AddNoteResponse//Response//description
11 Jun 2013 13:47:44,254 INFO docNodes.getLength() :0
But when I am trying the same code on my local system it is working fine:
Entering .convertStringToDoc()...
Exiting .convertStringToDoc()...
soapDocument [SOAP-ENV:Envelope: null]
9
xpath is not null
elementName :/Envelope/Body/AddNoteResponse/Response/code
docNodes length:1
value :0
docNodes length2:1
addNoteResponse.getCode
xpath is not null
elementName :/Envelope/Body/AddNoteResponse/Response/description
docNodes length:1
value :Success
docNodes length2:1
This is the response on which I am working with:
<SOAP-ENV:Envelope >
<SOAP-ENV:Header>
<MessageHeader >
<TrackingMessageHeader>
<cng:version>v68</cng:version>
<cng:originalVersion>v68</cng:originalVersion>
<cng:messageId>45266</cng:messageId>
<cng:timeToLive>120000</cng:timeToLive>
<cng:conversationId>xxx</cng:conversationId>
<cng:dateTimeStamp>2013-06-05T10:01:41.09Z</cng:dateTimeStamp>
<cng:uniqueTransactionId>xasas</cng:uniqueTransactionId>
</TrackingMessageHeader>
<SecurityMessageHeader>
<cng:userName>ass</cng:userName>
<cng:userPassword>asas</cng:userPassword>
</SecurityMessageHeader>
<SequenceMessageHeader>
<cng:sequenceNumber>1</cng:sequenceNumber>
<cng:totalInSequence>1</cng:totalInSequence>
</SequenceMessageHeader>
</MessageHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<AddNoteResponse >
<Response>
<cng:code>0</cng:code>
<cng:description>Success</cng:description>
</Response>
</AddNoteResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Value I am interested in is:
<cng:code>0</cng:code>
<cng:description>Success</cng:description>

Categories

Resources