Java XML with namespace issue - java

I have this code:
org.w3c.dom.Document doc = docBuilder.parse(representation.getStream());
Element element = doc.getDocumentElement();
NodeList nodeList = element.getElementsByTagName("xnat:MRSession.scan.file");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
// do something with the current element
my problem is with getElementsByTagName("xnat:MRSession.scan.file")
my xml looks like this:
<?xml version="1.0" encoding="UTF-8"?><xnat:MRSession "REMOVED DATA IGNORE">
<xnat:sharing>
<xnat:share label="23_MR1" project="BOGUS_GSU">
<!--hidden_fields[xnat_experimentData_share_id="1",sharing_share_xnat_experimentDa_id="xnat_E00001"]-->
</xnat:share>
</xnat:sharing>
<xnat:fields>
<xnat:field name="studyComments">
<!--hidden_fields[xnat_experimentData_field_id="1",fields_field_xnat_experimentDat_id="xnat_E00001"]-->S</xnat:field>
</xnat:fields>
<xnat:subject_ID>xnat_S00002</xnat:subject_ID>
<xnat:scanner manufacturer="GE MEDICAL SYSTEMS" model="GENESIS_SIGNA"/>
<xnat:prearchivePath>/home/ryan/xnat_data/prearchive/BOGUS_OUA/20120717_131900137/23_MR1</xnat:prearchivePath>
<xnat:scans>
<xnat:scan ID="1" UID="1.2.840.113654.2.45.2.108830" type="SAG LOCALIZER" xsi:type="xnat:mrScanData">
<!--hidden_fields[xnat_imageScanData_id="1"]-->
<xnat:image_session_ID>xnat_E00001</xnat:image_session_ID>
<xnat:quality>usable</xnat:quality>
<xnat:series_description>SAG LOCALIZER</xnat:series_description>
<xnat:scanner manufacturer="GE MEDICAL SYSTEMS" model="GENESIS_SIGNA"/>
<xnat:frames>29</xnat:frames>
<xnat:file URI="/home/ryan/xnat_data/archive/BOGUS_OUA/arc001/23_MR1/SCANS/1/DICOM/scan_1_catalog.xml" content="RAW" file_count="29" file_size="3968052" format="DICOM" label="DICOM" xsi:type="xnat:resourceCatalog">
So Basically I need to be able to iterate through all the xnat:MRSession/xnat:scan/xnat:file
elements and make some changes. Problem is
getElementsByTagName("xnat:MRSession.scan.file")
Is always null. Please help. Thanks

You could try the following using XPath:
Document document = // the parsed document
XPathFactory xPathFactory = XPathFactory.newInstance();
NodeList allFileNodes = xPathFactory.newXPath().evaluate("\\XNAT_NAMESPACE:file", document.getDocumentElement(), XPathConstants.NODESET);
Instead XNAT_NAMESPACE you would need to specify the exact namespace that is meant with the prefix "xnat" in your example.

Related

Best way to reach the tag I want in an XML file when it's repeated?

first post in here. I have an XML file that includes the tag "usine" multiple times and I'm doing it in a way that does not seem right and I want to see if there's a more optimal way to do it. This is my first time working with XML and Node/NodeList so I'm still getting familiar with it.
Here is the XML file
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<metadonnees>
<usine type="usine-matiere">
<icones>
<icone type="vide" path="src/ressources/UMP0%.png"/>
<icone type="un-tiers" path="src/ressources/UMP33%.png"/>
<icone type="deux-tiers" path="src/ressources/UMP66%.png"/>
<icone type="plein" path="src/ressources/UMP100%.png"/>
</icones>
<sortie type = "metal"/>
<interval-production>100</interval-production>
</usine>
<usine type="usine-aile">
<icones>
<icone type="vide" path="src/ressources/UT0%.png"/>
<icone type="un-tiers" path="src/ressources/UT33%.png"/>
<icone type="deux-tiers" path="src/ressources/UT66%.png"/>
<icone type="plein" path="src/ressources/UT100%.png"/>
</icones>
<entree type="metal" quantite="2"/>
<sortie type="aile"/>
<interval-production>50</interval-production>
</usine>
</metadonnees>
<simulation>
<usine type="usine-matiere" id="11" x="32" y="32"/>
<usine type="usine-aile" id="21" x="320" y="32"/>
<chemins>
<chemin de="11" vers="21" />
<chemin de="21" vers="41" />
</chemins>
</simulation>
For example, if I want to retrieve the x value of 'usine type="usine-aile"' in the simulation tag, here is the code I use :
NodeList nList = doc.getElementsByTagName("simulation");
Node positionNode = nList.item(0);
Element elementPosition = (Element) positionNode;
NodeList cooList = elementPosition.getElementsByTagName("usine");
Node cooNode = cooList.item(0);
Element cooElem = (Element) cooNode;
System.out.println(cooElem.getAttribute("x"));
Basically I have to make two NodeLists because the I want is in the tag and not the one in the tag, so the first NodeList is to locate me in the tag, then I go deeper making a new NodeList to find the I want. Is there a better way to do this? I'm probably doing it a wrong way so I wish to know your answers. Thanks
First, Get elements by tag name (e.g get elements of usine), it returns a Nodelist of that tag. e.g in simulation you have two usine tag(a NodeList with lenght of 2).
Second, you can iterate this Nodelist and do whatever you want to each node (element), for example you can get the attribute of each usine tag(
x , y, id)
In summary
1- Get element by tag name (NodeList)
2- Iterate Nodelist
3- Process the nodes (e.g Get attribute of each node in the iteration process (x,y,id)
I coded your scenario as follows
public static void main(String argv[]) throws ParserConfigurationException, IOException, SAXException {
//Read xml file
File fXmlFile = new File("/test.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
//Get usine nodes
NodeList nodeList = doc.getElementsByTagName("usine");
//Iterate nodeList
for (int temp = 0; temp < nodeList.getLength(); temp++) {
//Get each node and process it
Node node = nodeList.item(temp);
if (node.getNodeType() == Node.ELEMENT_NODE) {
//Print attributes of the node
Element element = (Element) node;
System.out.println("X = " + element.getAttribute("x"));
System.out.println("Y = " + element.getAttribute("y"));
System.out.println("ID = " + element.getAttribute("id"));
}
}
}
In this post, we're using DOM Parser for parsing XML, you can use this link to become more familiar with other XML processing libraries
like: SAX Parser, StAX Parser and JAXB, these are much better than DOM Parser in terms of speed and performance.

Java XML XPath Full XML

got a little problem. I have the following code:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("result1.xml");
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("//element");
String elements = (String) expr.evaluate(doc, XPathConstants.STRING);
What i get :
jcruz0#exblog.jp
Cheryl
Blake
195115
What i want:
<person>
<email>jcruz0#exblog.jp</email>
<firstname>Cheryl</firstname>
<lastname>Blake</lastname>
<number>195115</number>
</person>
So as you can see i want the full XML tree. Not just the NodeValue.
Maybe somebody knows the trick.
Thanks for any help.
You got the string value of the selected XML element because you specified XPathConstants.STRING to XPathExpression.evaluate().
Instead, specify a return type of XPathConstants.NODE if you know for sure that your XPath will select a single element,
String elements = (String) expr.evaluate(doc, XPathConstants.NODE);
or XPathConstants.NODESET for multiple elements, which you would then iterate over to process as necessary.
Something like this can be done.
XPathExpression expr = xpath.compile("/person");
NodeList elements = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < elements.getLength(); i++) {
// the person node
System.out.println(elements.item(i).getNodeName());
for (int x = 0; x < elements.item(i).getChildNodes().getLength(); x++) {
// the elements under person
if (elements.item(i).getChildNodes().item(x).getNodeType() == Node.ELEMENT_NODE) {
System.out.println("\t" + elements.item(i).getChildNodes().item(x).getNodeName() + " - " + elements.item(i).getChildNodes().item(x).getTextContent());
}
}
}
Output
person
email - jcruz0#exblog.jp
firstname - Cheryl
lastname - Blake
number - 195115
You can use the nodes to do what you want, or wrap them in < and > if you just want to print them.

DOM parsing in Java not able to get the nested notes

I have to parse an xml file in which I have many name value pairs.
I have to update the value in case it matches a given name.
I opted for DOM parsing as it can easily traverse any part and can quickly update the value.
It is however giving me some wired results when I am running it on my sample file.
I am new to DOM so if someone can help it can solve my problem.
I tried various things but all resulting in either null values for content or #text node name.
I am not able to get the text content of the tag.
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(xmlFilePath);
//This will get the first NVPair
Node NVPairs = document.getElementsByTagName("NVPairs").item(0);
//This should assign nodes with all the child nodes of NVPairs. This should be ideally
//<nameValuePair>
NodeList nodes = NVPairs.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
// I think it will consider both starting and closing tag as node so checking for if it has
//child
if(node.hasChildNodes())
{
//This should give me the content in the name tag.
//However this is not happening
if ("Tom".equals(node.getFirstChild().getTextContent())) {
node.getLastChild().setTextContent("2000000");
}
}
}
Sample xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?><application>
<NVPairs>
<nameValuePair>
<name>Tom</name>
<value>12</value>
</nameValuePair>
<nameValuePair>
<name>Sam</name>
<value>121</value>
</nameValuePair>
</NVPairs>
#getChildNodes() and #getFirstChild() returns all kinds of nodes, not just Element nodes, and in this case the first child of <name>Tom</name> is a Text node (with newline and blanks). So your test will never return true.
However, in cases like this, it always much more convenient to use XPath:
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xpath.evaluate(
"//nameValuePair/value[preceding-sibling::name = 'Tom']", document,
XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
node.setTextContent("2000000");
}
I.e., return all <name> elements that has a preceding sibling element <name> with value 'Tom'.

Child elements of DOM

I have this XML file:
<scene>
<texture file="file1.dds"/>
<texture file="file2.dds"/>
...
<node name="cube">
<texture name="stone" unit="0" sampler="anisotropic"/>
</node>
</scene>
I need all child element of 'scene' that are named "texture", but with this code:
Element rootNode = document.getDocumentElement();
NodeList childNodes = rootNode.getElementsByTagName("texture");
for (int nodeIx = 0; nodeIx < childNodes.getLength(); nodeIx++) {
Node node = childNodes.item(nodeIx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
// cool stuff here
}
}
i also get the 'texture' elements which are inside 'node'.
How can i filter these out? Or how can i get only the elements that are direct childs of 'scene'?
You can do it using Xpath, consider the following example taken from the JAXP Specification 1.4 (which I recommend you to consult for this):
// parse the XML as a W3C Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.Document document = builder.parse(new File("/widgets.xml"));
// evaluate the XPath expression against the Document
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/widgets/widget[#name='a']/#quantity";
Double quantity = (Double) xpath.evaluate(expression, document, XPathConstants.NUMBER);
I found myself a solution that works fine:
Element parent = ... ;
String childName = "texture";
NodeList childs = parent.getChildNodes();
for (int nodeIx = 0; nodeIx < childs.getLength(); nodeIx++) {
Node node = childs.item(nodeIx);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getNodeName().equals(name)) {
// cool stuff here
}
}

How to get value in XML using Java?

I have tried a lot of times but I did not how to retrive a value from XML using Java. I tried to use DOM and Xpath. Please help. I can use a String Writer to printout the XML so I know the XML is not empty.
Document doc = parseXML(connection.getInputStream());
doc.getDocumentElement().normalize();
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xPath.compile("/xml_api_reply/weather/current_conditions/temp_f/text()");
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).getNodeValue());
}
The content of XML :
<xml_api_reply version="1">
<weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0">
<current_conditions>
<condition data="Clear"/>
<temp_f data="49"/>
<temp_c data="9"/>
</current_conditions>
</weather>
</xml_api_reply>
It seems that it did not go in to the for loop because nodes is null.
Your XPath expression evaluates to the (non existant) text-nodes underneath temp_f. Yet, you need the value of the data attribute:
/xml_api_reply/weather/current_conditions/temp_f/#data
may do the trick.
Did you try this implementation?
http://www.mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/

Categories

Resources