I have the following XML:
<ConfigGroup Name="Replication">
<ValueInteger Name="ResponseTimeout">10</ValueInteger>
<ValueInteger Name="PingTimeout">2</ValueInteger>
<ValueInteger Name="ConnectionTimeout">10</ValueInteger>
<ConfigGroup Name="Pool">
<ConfigGroup Name="1">
<ValueString Encrypted="false" Name="Host">10.20.30.40</ValueString>
<ValueInteger Name="CacheReplicationPort">8899</ValueInteger>
<ValueInteger Name="RadiusPort">12050</ValueInteger>
<ValueInteger Name="OtherPort">4868</ValueInteger>
</ConfigGroup>
<ConfigGroup Name="2">
<ValueString Encrypted="false" Name="Host">10.20.30.50</ValueString>
<ValueInteger Name="CacheReplicationPort">8899</ValueInteger>
<ValueInteger Name="RadiusPort">12050</ValueInteger>
<ValueInteger Name="OtherPort">4868</ValueInteger>
</ConfigGroup>
</ConfigGroup>
</ConfigGroup>
I just wondering what is the simplest way to parse this XML in Java - I want the value from the two host elements (e.g. 10.20.30.40 and 10.20.30.50). Note there may be more than two pool entries (or none at all).
I'm having trouble finding a simple example of how to use the various XML parsers for Java.
Any help is much appreciated.
Thanks!
The simplest way to search for what you are looking for, would be XPath.
try {
//Load the XML File
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document configuration = builder.parse("configs.xml");
//Create an XPath expression
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
XPathExpression expr = xpath.compile("//ConfigGroup/ValueString[#Name='Host']/text()");
//Execute the XPath query
Object result = expr.evaluate(configuration, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
//Parse the results
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i).getNodeValue());
}
} catch (ParserConfigurationException e) {
System.out.println("Bad parser configuration");
e.printStackTrace();
} catch (SAXException e) {
System.out.println("SAX error loading the file.");
e.printStackTrace();
} catch (XPathExpressionException e) {
System.out.println("Bad XPath Expression");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IO Error reading the file.");
e.printStackTrace();
}
The XPath expression
"//ConfigGroup/ValueString[#Name='Host']/text()"
looks for ConfigGroup elements anywhere in your XML, then finds ValueString elements within the ConfigGroup elements, that have a Name attribute with the value "Host". #Name=Host is like a filter for elements with the name ValueString. And text() at the end, returns the text node of the selected elements.
Java XPath API allows to do it easily. The following xpath expression
//ValueString[#Name='Host']
should match what you want. Here is how to use it with the API :
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(yourXml.getBytes());
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodeList = (NodeList) xpath.compile("//ValueString[#Name='Host']").evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
String ip = ((Element) nodeList.item(i)).getTextContent();
// do something with your ip
}
You could use SAXON
String vs_source = "Z:/Code_JavaDOCX/1.xml";
Processor proc = new Processor(false);
net.sf.saxon.s9api.DocumentBuilder builder = proc.newDocumentBuilder();
XPathCompiler xpc = proc.newXPathCompiler();
try{
XPathSelector selector = xpc.compile("//output").load();
selector.setContextItem(builder.build(new File(vs_source)));
for (XdmItem item: selector)
{
System.out.println(item.getStringValue());
}
}
catch(Exception e)
{
e.printStackTrace();
}
Related
TLDR of what I'm trying to do:
Use an xml document to store representation of classes.
Use some parser class to recurse through the file and instantiate instances of those classes.
I am currently having issues with getting child elements (and not grandchildren) of the nodeList.
Thanks in Advance.
Suppose I have the following xml document
====== data.xml ======
<document>
<tag>
<child1> some content here </child1>
<child2> some other content </child2>
</tag>
<tag>
<child1> interesting content here </child1>
<child2>
<tag>
<child1> a b c d </child1>
<child2> e f g h </child2>
</tag>
</child2>
</tag>
</document>
I have tried using the xFile parser to get all tag nodes. However, when I do the following:
public static void parseXML() {
File file = new File("src//data//data.xml");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = null;
try {
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = null;
try {
doc = documentBuilder.parse(file);
} catch (SAXException | IOException e) {
e.printStackTrace();
}
try {
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
XPathExpression expr = xPath.compile("//document//tag");
NodeList nodeList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(i);
System.out.println(nodeList.item(i).getTextContent());
}
} catch (XPathExpressionException e) {
e.printStackTrace();
}
}
I get the following output:
0
some content here
some other content
1
interesting content here
a b c d
e f g h
2
a b c d
e f g h
How do I get it to ONLY return the <tag> elements which are directly nested in <document> (because the path provided to xPath.compile(String string); is //document//tag
To answer the specific question you have posed - I would change this
XPathExpression expr = xPath.compile("//document//tag");
to this
XPathExpression expr = xPath.compile("/document/tag[1]/*");
The // matches all sub nodes and according to your structure you don't have any.
I just discovered XPath and I'm trying to use it in order to parse an XML file. I read a few courses about it, but I am stuck with a problem. When I try to get a NodeList from the file, the getLength() method always returns 0.
However, when I try a
document.getElementsByTagName("crtx:env").getLength()
The output is correct (7 in my case).
I do not really understand, because my nodelist is built according to my Document, the output should be similar, isn't it ?
Here is a part of my code :
IFile f = (IFile) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor().getEditorInput().getAdapter(IFile.class);
String fileURL = f.getLocation().toOSString();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document document = null;
if (builder != null){
try{
document = builder.parse(fileURL);
System.out.println("DOCUMENT URI : " + document.getDocumentURI());
} catch (Exception e){
e.printStackTrace();
}
} else {
System.out.println("builder null");
}
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodeList = null;
try {
nodeList = (NodeList) xPath.compile("crtx:env").evaluate(document, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
e.printStackTrace();
}
System.out.println("NODELIST SIZE : " + nodeList.getLength());
System.out.println(document.getElementsByTagName("crtx:env").getLength());
}
The first System.out.println() returns coherent output (a good URI), but the two last lines return a different number.
Any help would be appreciated.
Thanks for reading.
XPath is defined for XML with namespaces so set
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setNamespaceAware(true);
Then to use a path with a namespace prefix you need to use https://docs.oracle.com/javase/7/docs/api/javax/xml/xpath/XPath.html#setNamespaceContext%28javax.xml.namespace.NamespaceContext%29 to bind the prefix(es) used to namespace URIs, see https://xml.apache.org/xalan-j/xpath_apis.html#namespacecontext for an example
With a namespace aware DOM you will need to change your getElementsByTagName call to use getElementsByTagNameNS however.
I'm trying to read the value of "release" tag of a remote XML file and return it's value .I'm able to find the value of "release" tag using getElementText() but not by getElementValue()
Java Code..
try {
URL url1 = new URL("http://hsv-artifactory.emrsn.org:8081/artifactory/libs-release-local/com/avocent/commonplatform/cps/symbols/gdd/GDDResources/maven-metadata.xml");
XMLStreamReader reader1 = XMLInputFactory.newInstance().createXMLStreamReader(url1.openStream());
String Latest = null;
while (reader1.hasNext()) {
if (reader1.next() == XMLStreamConstants.START_ELEMENT) {
if (reader1.getLocalName().equals("release")) {
Latest = reader1.getElementText();
break;
}
}
}
System.out.println("Latest version in Artifactory is :"+Latest);
} catch (IOException ex) {
// handle exception
Logger.getLogger(SVNRepoConnector1.class.getName()).log(Level.SEVERE, null, ex);
} catch (XMLStreamException ex) {
// handle exception
Logger.getLogger(SVNRepoConnector1.class.getName()).log(Level.SEVERE, null, ex);
} finally {
// close the stream
}
In the above code the value is being stored in a String variable but i want to store it in an integer variable so that i can perform operations like addition,subtraction on it afterwards..Please Help
DOM Solution:
URL url1 = new URL("http://hsv-artifactory.emrsn.org:8081/artifactory/libs-release-local/com/avocent/commonplatform/cps/symbols/gdd/GDDResources/maven-metadata.xml");
InputSource xmlInputSource = new InputSource(url1.openStream());
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document dom = dBuilder.parse(xmlInputSource);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("//release");//all release elements
NodeList nodes = (NodeList) expr.evaluate(e,XPathConstants.NODESET);
ArrayList<Integer> releaseList = new ArrayList<Integer>();
for (int i = 0; i < nodes.getLength(); i++) {
Element releaseElem = (Element) nodes.item(i);
releaseList.add(Integer.parseInt(releaseElem.getText()));
}
Just catch the exceptions.
Hye I am new to read XML File using Java my problem is that I have been trying to read an xml and between a specific tag I want to get the required data I am using XPath and my query is:
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#type='STRING']";
It works fine and my specific Tag to read from is:
<ATTRIBUTE name="Description" type="STRING"> SOME TEXT </ATTRIBUTE>
But I want to read the data inside only these types of Tags so that my output should be:
SOME TEXT
inside the tag!
can somebody help me how can I do this Please I am new to xml reading! Trying my best as:
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#name='Description' and ./type/text()='STRING']";
But it wont give me any output!
thanks in advance
My Code:
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
org.w3c.dom.Document document = builder.parse(
new FileInputStream("c:\\y.xml"));
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#name='Description'and #type='STRING']";
System.out.println(expression);
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getFirstChild().getNodeValue());
}
} catch (ParserConfigurationException | SAXException | IOException e) {
System.out.print(e);
}
There is a problem with my code cant figure out what!
This code works fine for me with the changed XPath to:
"/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#name='Description'][#type='STRING']":
private static final String EXAMPLE_XML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<ADOXML adoversion=\"Version 5.1\" username=\"kvarga\" database=\"adonisdb\" time=\"08:55\" date=\"30.11.2013\" version=\"3.1\">" +
"<MODELS>" +
"<MODEL version=\"\" applib=\"ADONIS BPMS BP Library 5.1\" libtype=\"bp\" modeltype=\"Business process model\" name=\"Product development\" id=\"mod.25602\">" +
"<MODELATTRIBUTES>" +
"<ATTRIBUTE name=\"Version number\" type=\"STRING\"> </ATTRIBUTE>" +
"<ATTRIBUTE name=\"Author\" type=\"STRING\">kvarga</ATTRIBUTE>" +
"<ATTRIBUTE name=\"Description\" type=\"STRING\">I WANT THIS PARA 2</ATTRIBUTE>" +
"</MODELATTRIBUTES>" +
"</MODEL>" +
"</MODELS>" +
"</ADOXML>";
public static void main(String[] args) {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(new ByteArrayInputStream(EXAMPLE_XML.getBytes()));
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#name='Description'][#type='STRING']";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println("###" + nodeList.item(i).getFirstChild().getNodeValue() + "###");
}
} catch (Exception e) {
System.out.print(e);
}
}
OUTPUT:
###I WANT THIS PARA 2###
The mentioned code works fine.
You can try other way also to get the text node -
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE/text()";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
System.out.println(nodeList.item(0).getNodeValue());
The below code prints the element contents of my XML file, however, for the life of me I have been unsuccessful at extracting the element values and putting them in a map or other type of array or list. Any help would be greatly appreciated!!!!
public class client
{
public static void main(String[] args )
{
int length = 0;
String [] array;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
//Using factory get an instance of document builder
DocumentBuilder builder = factory.newDocumentBuilder();
//create the document by parsing the actual file
Document doc = builder.parse(new File ("server.xml"));
//creat an XPath to be used in the extraction of the nodes
XPathFactory xPFactory = XPathFactory.newInstance();
XPath path = xPFactory.newXPath();
//Extract ports
XPathExpression portExpr
= path.compile("//configuration/hostInfo/port");
//Extract hosts
XPathExpression hostExpr
= path.compile("//configuration/hostInfo/host");
Object pResult = portExpr.evaluate(doc, XPathConstants.NODESET);
Object hResult = hostExpr.evaluate(doc, XPathConstants.NODESET);
NodeList pNodes = (NodeList) pResult;
NodeList hNodes = (NodeList) hResult;
array = new String [(pNodes.getLength())*2];
array = populateArray(array, pNodes, hNodes);
for (int k = 0; k < array.length; k++)
System.out.println( k+ "="+ array[k]);
}catch (Exception e) {
e.printStackTrace();
}
}
public static String[] populateArray (String array[], NodeList pNodes, NodeList hNodes){
array[0]=pNodes.item(0).getTextContent();
array[1]=hNodes.item(1).getTextContent();
for (int i = 1; i < pNodes.getLength(); i++){
array[2*i]= pNodes.item(i).getTextContent();
array[(2*i)+1]= hNodes.item(i).getTextContent();
}
return array;
}
}
XML FILE
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<hostInfo>
<port>8189</port>
<host>localhost</host>
</hostInfo>
<hostInfo>
<port>8190</port>
<host>localhost</host>
</hostInfo>
<hostInfo>
<port>8191</port>
<host>localhost</host>
</hostInfo>
</configuration>
You can do path.compile that will return a XPathExpression object. Then you can call evaluate to get an array of NodeList.
Take a look at http://www.ibm.com/developerworks/library/x-javaxpathapi.html and http://download.oracle.com/javase/1.5.0/docs/api/javax/xml/xpath/package-summary.html .