how to extract entire xml element from xml document - java

all the examples about parsing xml elements/nodes, that i've found, are about how to extract node attributes/values etc from xml document.
Im interested on how should i extract an entire element from opening tag to closing tag.
Example:
from xml document
<?xml version="1.0"?>
<Employees>
<Employee emplid="1111" type="admin"/>
</Employees>
i would get the complete element
<Employee emplid="1111" type="admin"/>
to saving it in a String variable
Thanks in advance

You can either do the parsing yourself, or use Android's XML parser. This shows how to use the latter.
If you use Android's parser you probably have to parse it completely, and then construct the string <Employee emplid="1111" type="admin"/> by hand.

For now this is the best solution.
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
...
//xml document
String xml = "<?xml version=\"1.0\"?><Employees><Employee emplid=\"1111\" type=\"admin\"/></Employees>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document document = parser.parse(new ByteArrayInputStream(xml.getBytes()));
//getting the target element
NodeList list=document.getElementsByTagName("Employee");
Node node=list.item(0);
//writing the element in the string variable
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
StringWriter buffer = new StringWriter();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(node), new StreamResult(buffer));
String str = buffer.toString();
System.out.println(str);
...
Inspired by this thread

Related

How to set prefix for the attribute in xml using java

I like to set prefix for attribute while creating XML file using Java.
The result that I needed is
<entry gd:etag="*">
<id>Text</id>
</entry>
But I'm getting
<entry etag="*">
<id>Text</id>
</entry>
The code that I have written is
DocumentBuilderFactory docBuildFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuildFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element entry = doc.createElement("entry");
entry.setAttribute("etag","*");
doc.appendChild(entry);
Element id = doc.createElement("id");
id.setTextContent("Text");
entry.appendChild(id);
.....
I have no idea how to set prefix for the attributes. Can someone suggest me how to do this?
You need to set the DocumentBuilderFactory to be namespace aware, and you need to set the namespace for that prefix and use setAttributeNS for an attribute with an XML namespace.
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class Entry {
public static void main(String[] args)
throws IOException, ParserConfigurationException, TransformerException {
String ns = "http://schemas.google.com/g/2005"; // just a guess
DocumentBuilderFactory docBuildFactory = DocumentBuilderFactory.newInstance();
docBuildFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docBuildFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element entry = doc.createElement("entry");
entry.setAttributeNS(ns, "gd:etag", "*");
doc.appendChild(entry);
Element id = doc.createElement("id");
id.setTextContent("Text");
entry.appendChild(id);
printDocument(doc, System.out);
}
public static void printDocument(Document doc, OutputStream out)
throws IOException, TransformerException {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "UTF-8")));
}
}
Output:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<entry xmlns:gd="http://schemas.google.com/g/2005" gd:etag="*">
<id>Text</id>
</entry>
Replace the namespace URN with the correct one; I just guessed at it based on Googling the gd:etag prefix, which brought up some Google Data API and Google Contacts API stuff.
SimpleXml can do it:
final SimpleXml simple = new SimpleXml();
final Element element =
element("entry").attribute("gd:etag", "*")
.child(element("id").text("Text"));
System.out.println(simple.domToXml(element));
Will output:
<entry gd:etag="*"><id>Text</id></entry>
From maven central:
<dependency>
<groupId>com.github.codemonstur</groupId>
<artifactId>simplexml</artifactId>
<version>1.4.0</version>
</dependency>

Split XML using a JDOM Java

I have following XML string.
<Engineers>
<Engineer>
<Name>JOHN</Name>
<Position>STL</Position>
<Team>SS</Team>
</Engineer>
<Engineer>
<Name>UDAY</Name>
<Position>TL</Position>
<Team>SG</Team>
</Engineer>
<Engineer>
<Name>INDRA</Name>
<Position>Director</Position>
<Team>PP</Team>
</Engineer>
</Engineers>
I need to split this xml into smaller xml strings when Xpath is given as Engineers/Enginner.
Smaller xml strings are as follows
<Engineer>
<Name>INDRA</Name>
<Position>Director</Position>
<Team>PP</Team>
</Engineer>
<Engineer>
<Name>JOHN</Name>
<Position>STL</Position>
<Team>SS</Team>
</Engineer>
I have implemented following using saxon xpath and JDOM.
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.DocumentInfo;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.s9api.DocumentBuilder;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.xpath.XPathFactoryImpl;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.junit.Test;
import org.xml.sax.InputSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;
public void testXML() throws XPathFactoryConfigurationException, XPathExpressionException, Exception {
System.setProperty("javax.xml.xpath.XPathFactory:" + NamespaceConstant.OBJECT_MODEL_JDOM,
"net.sf.saxon.xpath.XPathFactoryImpl");
XPathFactory xPathFactory = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_JDOM);
XPath xPath = xPathFactory.newXPath();
InputSource inputSource = new InputSource(new File(filename).toURI().toString());
SAXSource saxSource = new SAXSource(inputSource);
Configuration config = ((XPathFactoryImpl) xPathFactory).getConfiguration();
DocumentInfo document = config.buildDocument(saxSource);
XPathExpression xPathExpression = xPath.compile("//Engineers/Engineer");
List matches = (List) xPathExpression.evaluate(document, XPathConstants.NODESET);
if (matches != null) {
for (Iterator iter = matches.iterator(); iter.hasNext(); ) {
NodeInfo node = (NodeInfo) iter.next();
System.out.println(node.getDisplayName() + " - " + node.getStringValue());
}
}
}
It gives following result.
Engineer -
JOHN
STL
SS
Engineer -
UDAY
TL
SG
Engineer -
INDRA
Director
PP
How can I change the code so that I get my desired output?Or is there a way to get the names of child attributes(Name,Position,Team) inside Engineer
If you are using JDOM for this work, you should consider using the native JDOM methods instead of the abstraction run through Saxon.
Consider something like:
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.xpath.XPathFactory;
import org.jdom2.xpath.XPAthExpression;
import org.jdom2.output.XMLOutputter;
import org.jdom2.input.SAXBuilder;
import org.jdom2.filter.Filters;
....
XPathExpression xpe = XPathFactory.instance()
.compile("//Engineers/Engineer", Filters.element());
Document doc = new SAXBuilder().build(new File(filename));
XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());
for (Element e : xpe.evaluate(doc)) {
xout.output(e, System.out);
}
I would do the splitting in XSLT:
<xsl:stylesheet ....>
<xsl:template match="Engineeers/Engineer">
<xsl:result-document href="{position()}.xml">
<xsl:copy-of select="."/>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
If you want the result as a list of JDOM documents then you can supply Saxon with an OutputURIResolver:
Controller controller = transformer.getUnderlyingController();
final Configuration config = controller.getConfiguration();
List<Document> jdomDocuments = new ArrayLis<Document>();
Controller.setOutputURIResolver(new OutputURIResolver() {
public Result resolve(href, base) {
return new JDOM2Writer(config.makePipelineConfiguration());
}
public void close(Result result) {
jdomDocuments.add(((JDOM2Writer)result).getDocument());
}
}
and on completion the results will be in jdomDocuments.

why xml file does not aligned properly after append the string in beginning and end of the file using java?

I have added the string in beginning and end of the XML File.but the alignment is not proper after getting the result.
My XML File:
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
import com.google.common.io.Resources;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URL;
import java.nio.charset.Charset;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class ModifyXMLFile {
public static void main(String args[]) {
try {
// Point the file directory path here
String directory = "C:\\Users\\n444479\\Desktop\\SA";
int test = new File("C:\\Users\\n444479\\Desktop\\SA").listFiles().length;
File[] files = new File(directory).listFiles();
// Loop the file to run all the XML files
for (int j = 0; j < test; j++) {
System.out.println(files[j]);
String filepathext = files[j].toString();
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filepathext);
/*
// XML file update starts here
// 1.Add the attribute element with value between the two XML
// Child elements
NodeList nodes = doc.getElementsByTagName("dummySegmentOne");
Text a = doc.createTextNode("value"); Element p =
doc.createElement("newNode"); p.appendChild(a);
nodes.item(0).getParentNode().insertBefore(p, nodes.item(0));
// 2.Add the attribute element without value between the two XML
// Child elements
NodeList nodesa =
doc.getElementsByTagName("customerLevelRegDocs"); Element q =
doc.createElement("dummySegmentOne");
nodesa.item(0).getParentNode().insertBefore(q,
nodesa.item(0));
// 3.Rename the element in parent and child both using the JAXP
// Parser
*/
// XSLT File:
String xsltResource = "C:\\Users\\n444479\\Desktop\\AB\\test.xml";
StringWriter xmlResultResource = new StringWriter();
Transformer xmlTransformer = TransformerFactory.newInstance().newTransformer(
new StreamSource(new File(xsltResource)));
xmlTransformer.transform(new StreamSource(new File(filepathext)),new StreamResult(xmlResultResource));
// XML file update end here
// write the content into XML file
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new String(filepathext));
transformer.transform(source, result);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
// Successful output once get it "Done"
String output = xmlResultResource.getBuffer().toString();
// Writing the transformed XML to a file
FileWriter fileWriter = new FileWriter(filepathext);
fileWriter.write(output);
fileWriter.close();
System.out.println("Done");
}
}
// Exception handling
catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SAXException sae) {
sae.printStackTrace();
}
}
}
Once the program executed the string get appended properly but the XML File alignment changed.
The output i am getting as below
<?xml version="1.0" encoding="UTF-8"?>{% from lxml import etree %}{% from StringIO import StringIO %}{% set tree = parse_xml(request_text) %}{% set namespaces = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/', 'wbs': 'http://xml.ama.com/ws/2009/01/WBS_Session-2.0.xsd'}%}<soap:Envelope xmlns:xalan="http://xml.apache.org/xalan" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><Session><SessionId>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SessionId', namespaces=namespaces)[0].text}}</SessionId><SequenceNumber>{{int(tree.xpath('//soapenv:Header/wbs:Session/wbs:SequenceNumber', namespaces=namespaces)[0].text)+1}}</SequenceNumber><SecurityToken>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SecurityToken', namespaces=namespaces)[0].text}}</SecurityToken></Session></soap:Header><soap:Body><reRoot><reNode> world</reNode></reRoot></soap:Body></soap:Envelope>
why the file not getting appeneded
The reason is that DataInputStream.readLine discards the newline character. So, you'll have to append it yourself.
Moreover:
Take in account that the resulting XML is incorrect, because the original XML header turns out to be included in one node. The header (if present) must stay always before the root node.
To properly transform your input XML to a SOAP, I recommend you two alternatives:
Either transform it through an XSL stylesheet.
Or either build the resulting XML with DOM and include the source XML as one child node. Then, when serializing the whole document, you may specify indentation parameters.
Update
I suggest you this XSL:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">{% from lxml import etree %}{% from StringIO import StringIO %}{% set tree = parse_xml(request_text) %}{% set namespaces = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/', 'wbs': 'http://xml.ama.com/ws/2009/01/WBS_Session-2.0.xsd'}%}<soap:Envelope xmlns:xalan="http://xml.apache.org/xalan" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Session>
<SessionId>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SessionId', namespaces=namespaces)[0].text}}</SessionId>
<SequenceNumber>{{int(tree.xpath('//soapenv:Header/wbs:Session/wbs:SequenceNumber', namespaces=namespaces)[0].text)+1}}</SequenceNumber>
<SecurityToken>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SecurityToken', namespaces=namespaces)[0].text}}</SecurityToken>
</Session>
</soap:Header>
<soap:Body><xsl:copy-of select="."/>
</soap:Body>
</soap:Envelope>
</xsl:template>
</xsl:stylesheet>
In other words: It creates a SOAP message with a fixed format, and sets the input xml as the contents of the <soap:Body> node.
And the transformation code:
private static void transform(org.w3c.dom.Document doc, java.io.InputStream inputXsl, java.io.OutputStream out)
throws java.io.IOException,
javax.xml.transform.TransformerConfigurationException,
javax.xml.transform.TransformerException
{
javax.xml.transform.Templates templates=javax.xml.transform.TransformerFactory.newInstance().newTemplates(new javax.xml.transform.stream.StreamSource(inputXsl));
javax.xml.transform.Transformer transformer=templates.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
javax.xml.transform.Result result=new javax.xml.transform.stream.StreamResult(out);
javax.xml.transform.Source source=new javax.xml.transform.dom.DOMSource(doc);
if (doc.getInputEncoding() != null)
{
transformer.setOutputProperty("encoding", doc.getInputEncoding());
}
transformer.transform(source, result);
}
The whole result is re-indented by means of two causes:
The xsl:strip-space in the XSL.
The indent and indent-amount properties in the transformation.
The below XSL Stylesheet will be formatting the xml properly
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="/">
{% from lxml import etree %}{% from StringIO import StringIO %}{% set tree = parse_xml(request_text) %}{% set namespaces = {'soapenv': 'http://schemas.xmlsoap.org/soap/envelope/', 'wbs': 'http://xml.ama.com/ws/2009/01/WBS_Session-2.0.xsd'}%}
<soap:Envelope xmlns:xalan="http://xml.apache.org/xalan" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<Session>
<SessionId>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SessionId', namespaces=namespaces)[0].text}}</SessionId>
<SequenceNumber>{{int(tree.xpath('//soapenv:Header/wbs:Session/wbs:SequenceNumber', namespaces=namespaces)[0].text)+1}}</SequenceNumber>
<SecurityToken>{{tree.xpath('//soapenv:Header/wbs:Session/wbs:SecurityToken', namespaces=namespaces)[0].text}}</SecurityToken>
</Session>
</soap:Header>
<soap:Body><xsl:copy-of select="."/>
</soap:Body>
</soap:Envelope>
</xsl:template>
</xsl:stylesheet>
#Little Santi thanks for helping me and getting understand things.

JDom returns null

I am trying to parse an XML and the code that I use is as follows:
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
public class Main {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:comm3=\"http://www.csapi.org/schema/parlayx/common/v3_1\" xmlns:sms7=\"http://www.csapi.org/schema/parlayx/sms/notification/v3_1/local\">\r\n <SOAP-ENV:Header>\r\n <comm3:NotifySOAPHeader>\r\n <spId>37</spId>\r\n </comm3:NotifySOAPHeader>\r\n </SOAP-ENV:Header>\r\n <SOAP-ENV:Body SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n <sms7:notifySmsDeliveryReceipt>\r\n <sms7:correlator>123</sms7:correlator>\r\n <sms7:deliveryStatus>\r\n <address>tel:959257118550</address>\r\n <deliveryStatus>DeliveredToTerminal</deliveryStatus>\r\n </sms7:deliveryStatus>\r\n </sms7:notifySmsDeliveryReceipt>\r\n </SOAP-ENV:Body>\r\n</SOAP-ENV:Envelope>\r\n";
System.out.println("xml:");
System.out.println(xml);
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder loader = factory.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
Document doc = loader.parse(is);
NodeList nodeList = doc.getElementsByTagNameNS("http://www.csapi.org/schema/parlayx/sms/notification/v3_1/local", "correlator");
Element correlatorElement = (Element) nodeList.item(0);
System.out.println(correlatorElement);
NodeList addressNodeList = doc.getElementsByTagName("address");
System.out.println(addressNodeList.item(0));
}
}
Without throwing any exception, the code prints the results but what we get is not what we would expect.
xml:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:comm3="http://www.csapi.org/schema/parlayx/common/v3_1" xmlns:sms7="http://www.csapi.org/schema/parlayx/sms/notification/v3_1/local">
<SOAP-ENV:Header>
<comm3:NotifySOAPHeader>
<spId>37</spId>
</comm3:NotifySOAPHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<sms7:notifySmsDeliveryReceipt>
<sms7:correlator>123</sms7:correlator>
<sms7:deliveryStatus>
<address>tel:959257118550</address>
<deliveryStatus>DeliveredToTerminal</deliveryStatus>
</sms7:deliveryStatus>
</sms7:notifySmsDeliveryReceipt>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
[sms7:correlator: null]
[address: null]
Process finished with exit code 0
Why are the values null?
There is 3 reason, why ist not working:
The node really doesn't exist!
The node is in a different namespace and you need to use the version of the method that also accepts the namespace: Element#getChild(String, Namespace) or Element#getChildText(String, Namespace).
Most importantly, remember that these methods return only immediate descendents of a node! So if you're looking to get a node nested at the nth level, you will need to walk the tree to its parent and only then can you call #getChild() and actually get the child!

XML file containing multiple root elements

I have a file which contains multiple sets of root elements. How can I extract the root element one by one?
This is my XML
<Person>
<empid></empid>
<name></name>
</Person>
<Person>
<empid></empid>
<name></name>
</Person>
<Person>
<empid></empid>
<name></name>
</Person>
How can I extract one set of Person at a time?
Use java.io.SequenceInputStream to trick xml parser:
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MultiRootXML{
public static void main(String[] args) throws Exception{
List<InputStream> streams = Arrays.asList(
new ByteArrayInputStream("<root>".getBytes()),
new FileInputStream("persons.xml"),
new ByteArrayInputStream("</root>".getBytes())
);
InputStream is = new SequenceInputStream(Collections.enumeration(streams));
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
NodeList children = doc.getDocumentElement().getChildNodes();
for(int i=0; i<children.getLength(); i++){
Node child = children.item(i);
if(child.getNodeType()==Node.ELEMENT_NODE){
System.out.println("persion: "+child);
}
}
}
}
You cannot parse your file using an XML parser because your file is not XML. XML cannot have more than one root element.
You have to treat it as text, repair it to be well-formed, and then you can parse it with an XML parser.
If your XML is valid, using a SAX or DOM parser. Please consult the XML Developer's Kit Programmer's Guide for more details.

Categories

Resources