I have an XML document that looks like this:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="/resources/transform.xslt"?>
<map name="response">
<prop name="numConsumers">87</prop>
<prop name="numOutEventsQueued">17</prop>
<prop name="numOutEventsUnAcked">2131</prop>
<prop name="numOutEventsSent">538108577</prop>
</map>
I get the response as a string, so I parse it to XML and try to extract numConsumers (the value 87):
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xml)));
NodeList nodeList = doc.getChildNodes();
for(int i = 0; i < nodeList.getLength(); i++) {
String numConsumers = nodeList.item(i).getTextContent();
}
But the thing is, when i = 0, numConsumers is type="text/xsl" href="/resources/transform.xslt" and when i = 1, it is all the values of the child nodes, concatenated. What am I doing wrong? I'm aware that the current code is not explicitly looking for the node I want, but at this point I'm just trying to see if I can get to any of the nodes.
NodeList nodeList = doc.getChildNodes();
In XML DOM everything is a node. The document in your case has 2 nodes at document level the declaration node ('xml-stylesheet') and the document element ('map'). Depending on the configuration of the parser, if there are any white spaces (and schema , which you dont have, allows it) before or after document element, you would have got that.
One of the way to get what you are at is the below:
NodeList nodeList=doc.getDocumentElement().getElementsByTagName("prop");
for(int i=0;i<nodeList.getLength();i++{
String number=nodeList.item(i).getFirstChild().getNodeValue();
}
Notice the .getFirstChild().getNodeValue(), in XML DOM everything is a node, internal content of an element node is not the value of the node, it is the first child of the node, the value of the first child is '87' or some other value.
Related
I am trying to add sequence of nodes under a node, below is my reference xml:
<?xml version="1.0" encoding="UTF-8"?>
<transformation>
<info>
<name>Bulkload</name>
<description/>
<extended_description/>
<trans_version/>
<trans_type>Normal</trans_type>
<trans_status>0</trans_status>
<directory>/</directory>
</info>
<connection>
<name>con_name</name>
<server>server</server>
<type>SYBASE</type>
<access>Native</access>
<database>database</database>
<port>port</port>
<username>user</username>
<password>Encrypted xyz</password>
</connection>
<step>
<name>Extract</name>
<type>TextFileOutput</type>
<fields>
**HERE**
<field>
</field>
</fields>
<cluster_schema/>
<remotesteps> <input> </input> <output> </output> </remotesteps> <GUI>
<xloc>300</xloc>
<yloc>168</yloc>
<draw>Y</draw>
</GUI>
</step>
</transformation>
I want to add below xml block inside field tag:
<field>
<name>field_name</name>
<type>Integer</type>
<format>#;-#</format>
<currency/>
<decimal>.</decimal>
<group>,</group>
<nullif/>
<trim_type>none</trim_type>
<length>9</length>
<precision>0</precision>
</field>
My requirement is to create new xml documents from the above template. I only found a method in Xpath to insert node before a node so I updated my template and added a blank field node in it inside fields node and with that I was able to insert a node with the below code:
File dest =new File("H:\\Project_Documents\\reference.ktr");
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setIgnoringComments(true);
DocumentBuilder builder = factory.newDocumentBuilder();
String newLine = System.getProperty("line.separator");
Document document = builder.parse(dest);
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
NodeList nodes = document.getElementsByTagName("field");
Text a = document.createTextNode("Anup");
Element p =document.createElement("field");
p.appendChild(a);
nodes.item(0).getParentNode().insertBefore(p, nodes.item(0));
but again I faced the dame problem for child nodes i.e name, type, format, etc. Could anybody please show me a way to achieve my purpose?
If I cannot achieve it with Xpath then which parser I should use?
One solution, which works:
You have to manage two XML Documents, find the tag you want, and replace.
With XPath you can select more precisely, but no use there.
1 get a DOM for your global XML
Document document= ...
2 get the node you want to insert
Document document_to_insert = builder.parse(new InputSource(new StringReader(xml_to_insert))); // ...
//GET NODE field
NodeList nodes_field_to_insert=document_to_insert.getElementsByTagName("field");
Element node_field_to_insert=null;
for(int i=0; i<nodes_field_to_insert.getLength(); i++)
{
Node the_node = nodes_field_to_insert.item(i);
// WE TAKE THE FIRST ONE
if(the_node instanceof Element)
{
node_field_to_insert=(Element) the_node;
break;
}
}
3 go to the field node in the global XML
4 replace inside the node
// GET NODE field
NodeList nodes=document.getElementsByTagName("field");
for(int i=0; i<nodes.getLength(); i++)
{
Node the_node = nodes.item(i);
if(the_node instanceof Element)
{
Element a_child = (Element) the_node;
Node newNode = document.importNode(node_field_to_insert, true);
// FATHER
Node the_parent=a_child.getParentNode();
the_parent.replaceChild(newNode,a_child);
// WE STOP
break;
}
}
<root>
<h id="1">
<d value="1,2,3,4,5"><open>10:00</open><close>23:00</close></d>
<d value="6"><open>10:00</open><close>2:00</close></d>
<d value="7"><open>10:00</open><close>21:00</close></d>
</h>
<h id="2">
</h>
</root>
Here I have the XML which root has list of <h> tagged nodes. Now I need to break these into parts and set it into different variables (add into a map).
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(new ByteArrayInputStream(data.getBytes("utf-8"))));
NodeList nList = doc.getElementsByTagName("h");
for (int i = 0; i < nList.getLength(); i++)
{
Node nNode = nList.item(i);
System.out.println(nNode.getAttributes().getNamedItem("id") + " " + ?????);
}
what should I call in order to get the value (String value) of a nNode ?
Here is what Im looking for as the asnwer for the above code once some one fills the ????
1 <h id="1"><d value="1,2,3,4,5"><open>10:00</open><close>23:00</close></d><d value="6">open>10:00</open><close>2:00</close></d><d value="7"><open>10:00</open><close>21:00</close></d></h>
2 <h id="2"></h>
And i don't mind having as root element
You can use Node.getTextContent() to conveniently get all the text of a node (gets text of children as well).
See Parsing xml file contents without knowing xml file structure for a short example.
If you're trying to get the value attributes of the d nodes (I can't actually tell, your question is slightly unclear to me), then it would be different -- for that you would iterate through the children of each h node (use getChildNodes() or getFirstChild() + getNextSibling()) then grab their value attributes just as you are getting the id attribute of the h nodes (the above link also shows an example of iterating through child nodes).
Have you tried jDom library? http://www.jdom.org/docs/apidocs/org/jdom2/output/XMLOutputter.html
XMLOutputter outp = new XMLOutputter();
String s = outp.outputString(your_jdom_element);
Have you tried nNode.toString() if you are using Node from javax.xml.soap.Node.
You can use that:
http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Node.html#getTextContent()
but your sample nNode has other nodes, not just text. It seems you need helper method to construct String from child nodes.
Pass your nNode to nodeToString
XML Node to String in Java
I have a tiny little problem parsing an XML file in Java (Android).
I have an XML file that is like this:
<Events>
<Event Name="Olympus Has Fallen">
...
</Event>
<Event Name="Iron Man 3">
...
</Event>
</Events>
I already managed to get the NodeList by doing this:
URL url = new URL("********");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("Event");
Also I managed to get every single item of the NodeList by doing this:
for (int i = 0; i < nodeList.getLength(); i++) {
// Item
Node node = nodeList.item(i);
Log.i("film", node.getNodeName());
}
But this just Logs: "Event" instead of the value of the Name tag.
How do I output the value of this 'name' tag from the XML.
Can anyone help me with this one?
Thanks in advance!
But this just Logs: "Event" instead of the value of the Name tag.
Yes, because you're asking for the name of the element. There isn't a Name "tag" - there's a Name attribute, and that's what you should find:
// Only check in elements, and only those which actually have attributes.
if (node.hasAttributes()) {
NamedNodeMap attributes = node.getAttributes();
Node nameAttribute = attributes.getNamedItem("Name");
if (nameAttribute != null) {
System.out.println("Name attribute: " + nameAttribute.getTextContent());
}
}
(It's very important to be precise in terminology - it's worth knowing the difference between nodes, elements, attributes etc. It will help you enormously both when communicating with others and when looking for the right bits of API to call.)
I've got a section of XML that looks like this:
<entry>
<id>tag:example.com,2005:Release/343597</id>
<published>2012-04-10T11:29:19Z</published>
<updated>2012-04-10T12:04:41Z</updated>
<link type="text/html" href="http://example.com/projects/example1" rel="alternate"/>
<title>example1</title>
</entry>
I need to grab the link http://example.com/projects/example1 from this block. I'm not sure how to do this. To get the title of the project I use this code:
String title1 = children.item(9).getFirstChild().getNodeValue();
where children is the getChildNodes() object for the <entry> </entry> block. But I keep getting NullPointerExceptions when I try to get the node value for the <link> node in a similar way. I see that the XML code is different for the <link> node, and I'm not sure what it's value is.... Please advise!
The xpath expression to get that node is
//entry/link/#href
In java you can write
Document doc = ... // your XML document
XPathExpression xp = XPathFactory.newInstance().newXPath().compile("//entry/link/#href");
String href = xp.evaluate(doc);
Then if you need to get the link value of the entry with a specific id you can change the xpath expression to
//entry[id='tag:example.com,2005:Release/343597']/link/#href
Finally if you want to get all the links in the documents, if the document has many entry elements you can write
Document doc = ... // your XML document
XPathExpression xp = XPathFactory.newInstance().newXPath().compile("//entry/link/#href");
NodeList links = (NodeList) xp.evaluate(doc, XPathConstants.NODESET);
// and iterate on links
Here is the complete code:
DocumentBuilderFactory domFactory = DocumentBuilderFactory
.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("test.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("//entry/link/#href");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i));
}
I am trying to get an attribute of an xml node example:
<Car name="Test">
</Car>
I want to grab the name attribute of the car node.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(configFile);
doc.getDocumentElement().normalize();
NodeList layerConfigList = doc.getElementsByTagName("CAR");
Node node = layerConfigList.item(0);
// get the name attribute out of the node.
this is where i get stuck because the only method that looks like i can use is getAttributes() with returns a NamedNodeMap and im not sure how to extract it from that.
Your node is an Element so you just have to
Element e = (Element)node;
String name = e.getAttribute("name");
you can do it without using elements, like this:
//HtmlTag represents any arbitrary node that you are trying to get its "car" attribute
if("HtmlTag".equals(node.getNodeName()))
String nodeContent=node.getAttributes().getNamedItem("car").getNodeValue()