How to retrieve node element's value based on attribute name using dom & xml parsing
<ROOT>
<A>
<aa name="xyz">k,l,m </aa>
<aa name="pqr">a,b,h </aa>
<aa name="abc">s,t,r </aa>
...
</A>
<B>
<bb name="t1">r,st,t</bb>
...
</B>
</ROOT>
...
Fragment of implementation tried:
NodeList nodeList = <xmlDoc>.getElementsByTagName("aa");
for (int i = 0; i < nodeList.getLength(); i++)
{
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element element = (Element) node;
System.out.println(element.getTextContent());
// ? getNodeValue() // ? how to get by passing attribute name as matching criteria,
// f.e : how to get a,b,h printed for node aa with attribute name as pqr
For attribute it will be : element.getAttribute("name");
If you want to search by attribute, then
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nl = (NodeList)xpath.compile("//aa[#name='pqr']").evaluate(doc, XPathConstants.NODESET);
//Rest of the code same
*Please change the xpath according to your need. I did not run it myself, but you get the idea.
Related
I have an XML file like below:
<main>
<member>
<tag1>
<id>"123"</id>
</tag1>
</member>
<member>
<tag1>
<id>"222"</id>
<first>
<code>"1"</code>
<name>"x"<name>
</first>
</tag1>
</member>
<member>
<tag1>
<id>"321"</id>
</tag1>
</member>
<member>
<tag1>
<id>"333"</id>
<second>
<code>"1"</code>
<name>"y"<name>
</second>
<first>
<code>"2"</code>
<name>"z"<name>
</first>
</tag1>
</member>
</main>
I am able to loop through the list and get the "name" value in a list. I should print results in a CSV file which has columns such as "First name" and "second name" so at the time that I am reading these names I need to know which name is associated with which "parent" tag. In other words, I need to insert name under the tag "First" in the "First name" column and name under "second" tag under "second name".
So at the time that I am looping through I should check if the parent is "first" insert the name into "First name" and so on.
I have name Element as follow:
NodeList nameList=doc.getElementsByTagName("tag1");
...//some code to parse throught the rest of the elements
for (int temp = 0; temp < nameList.getLength(); temp++) {
Node nNode = nameList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE){
Element nElement=(Element) nNode;
System.out.println(nElement.getElementsByTagName("name").item(temp).getTextContent());
}
}
If I use the following to check it will give me "member1".
nElement.getParentNode().getNodeName()
How can I get "first" or "second" as parents of "name"? Or is there a better way to do this?
Note: the above code is part of my code which is really big because there are a lot of tags in this XML that needs to be parsed. I just added partial part of the code that is required for the information. If more is required, please let me know so that I can update my question.
I used XPath to solve the problem but still not getting the answer :
String expression="/main/member";
String fExpression="/main/member/tag1/first";
String sExpression="/main/member/tag1/second";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);
for (int i=0; i<nodeList.getLength();i++){
Node nNode=nodeList.item(i);
NodeList pLangList = (NodeList) xPath.compile(fExpression).evaluate(nNode, XPathConstants.NODESET);
NodeList sLangList = (NodeList) xPath.compile(sExpression).evaluate(nNode, XPathConstants.NODESET);
Node flangNode=pLangList.item(i);
Node slangNode=sLangList.item(i);
if (flangNode.getNodeType() == Node.ELEMENT_NODE){
Element fLangElement=(Element) plangNode;
System.out.println(i+"# primary"+fLangElement.getElementsByTagName("name").item(0).getTextContent());
}
if (slangNode.getNodeType() == Node.ELEMENT_NODE){
Element sLangElement=(Element) slangNode;
System.out.println(i+"# secondary"+sLangElement.getElementsByTagName("name").item(0).getTextContent());
}
//rest of the code
}
I used XPath but here is the issue: in the loop from 0 to length of the list, in iteration 0 it prints both x and y then on iteration 1, it prints z. where it should print x on iteration 1 and y, z on iteration 2! How do I solve this?
Note: I have updated the code with recent changes and still having same problem plus an error as follow:
0# first x
0# second y
1# first z
You can directly address the needed elements using xpath (java code part is all yours ;) )
Get 'member' tags and iterate them
String expression = "//member"";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);
Then for each of those nodes, get the other tags referencing the current node
String namex = "//tag1/name/text()";
NodeList namenodeList = (NodeList) xPath.compile(namex).evaluate(nNode, XPathConstants.NODESET);
Note that the first argument for evaluate() is the current 'node' and not 'doc'.
I was able to solve this problem as follow:
NodeList nameList=doc.getElementsByTagName("tag1");
...//some code to parse throught the rest of the elements
for (int temp = 0; temp < nameList.getLength(); temp++) {
Node nNode = nameList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE){
Element nElement=(Element) nNode;
int count=getChildElementCount(nElement); //it'll return the number of child nodes if there is any
if (count==1)
System.out.println(temp+" # "+nElement.getElementsByTagName("name").item(0).getTextContent());
else{
NodeList childNodes=nElement.getChildNodes();
int j=0;
for (int i=0;i<childNodes.getLength();i++){
if (childNodes.item(i).getNodeType() == Node.ELEMENT_NODE && j<count){
if(childNodes.item(i).getNodeName().contentEquals("second")){
//do something
j++;
}
if(childNodes.item(i).getNodeName().contentEquals("first")){
//do somehting
j++;
}
}
}
}
i am having issues when reading the attribute of a link,
this is the structure of my xml,
<entry>
<updated>
<title>
<link href="">
</entry>
i managed to read the date and title correctly but the href attribute of the link is not working.
Here is my code,
NodeList nList = doc.getElementsByTagName("entry");
System.out.println("============================");
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node node = nList.item(temp);
System.out.println(""); //Just a separator
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element eElement = (Element) node;
System.out.println("Date : " + eElement.getElementsByTagName("updated").item(0).getTextContent());
System.out.println("Title : " + eElement.getElementsByTagName("title").item(0).getTextContent());
// The below code is for reading href attribute of link,
NodeList node1 = eElement.getElementsByTagName("link");
Element eElement1 = (Element) node1;
System.out.println(eElement1.getAttribute("href"));
}
}
I am creating a new nodelist for the attributes of link but the code is not working.
error:
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl cannot be cast to org.w3c.dom.Element
at Demo.main(Demo.java:45)
A NodeList is not an Element and cannot be cast to one (successfully), so this code isn't going to work:
NodeList node1 = eElement.getElementsByTagName("link");
Element eElement1 = (Element) node1;
A NodeList is, as the name suggests, a list of nodes (and in your case, the nodes will be Elements). So this code would work for the first link:
NodeList list = eElement.getElementsByTagName("link");
Element eElement1 = (Element) list.item(0);
...whereupon your getAttribute should work fine, as Element has getAttribute.
Side note: If your library has support for newer query functions, you could also do this:
String href = ((Element)eElement.querySelector("entry")).getAttribute("href");
...because querySelector returns just the first match (not a list) (or null if no matches; if that's a possibility, add a guard to the above). But I don't know how well querySelector is supported outside of browsers yet.
// The below code is for reading href attribute of link,
NodeList node1 = eElement.getElementsByTagName("link");
Element eElement1 = (Element) node1;
NodeList will give you Node object not Element, you can get href value as follows,
String hrefValue = nodeList.item(0).
getAttributes().getNamedItem("href").getNodeValue();
I have a xml file
<Response>
<StatusCode>0</StatusCode>
<StatusDetail>OK</StatusDetail>
<AccountInfo>
<element1>value</element1>
<element2>value</element2>
<element3>value</element2>
<elementN>value</elementN>
</AccountInfo>
</Response>
And I want parse my elements in AccountInfo, but I dont know elements tag names.
Now Im using and have this code for tests, but in future I will recieve more elemenets in AccountInfo and I dont know how many or there names
String name="";
String balance="";
Node accountInfo = document.getElementsByTagName("AccountInfo").item(0);
if (accountInfo.getNodeType() == Node.ELEMENT_NODE){
Element accountInfoElement = (Element) accountInfo;
name = accountInfoElement.getElementsByTagName("Name").item(0).getTextContent();
balance = accountInfoElement.getElementsByTagName("Balance").item(0).getTextContent();
}
Heres 2 ways you can do it:
Node accountInfo = document.getElementsByTagName("AccountInfo").item(0);
NodeList children = accountInfo.getChildNodes();
or you can do
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList children = (NodeList) xPath.evaluate("//AccountInfo/*", document.getDocumentElement(), XPathConstants.NODESET);
Once you have your NodeList you can loop through them.
for(int i=0;i<children.getLength();i++) {
if(children.item(i).getNodeType() == Node.ELEMENT_NODE) {
Element elem = (Element)children.item(i);
// If your document is namespace aware use localName
String localName = elem.getLocalName();
// Tag name returns the localName and the namespace prefix
String tagName= elem.getTagName();
// do stuff with the children
}
}
I have a node that I receive as a result of selection by XPath.
Can I check if this node is an attribute?
Code example:
Document doc = builder.parse(new StringInputStream(xml));
XPathExpression expression = xpath.compile(path);
DTMNodeList result = (DTMNodeList) expression.evaluate(doc, XPathConstants.NODESET);
Node node = result.item(0);//how to check if this node is an attribute
Example XML:
<a atr='asdf'></a>
XPATH:
/a/#atr
try this
if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
...
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.