开发者

XPath - Get id attribute from parent element

i have following xml file:

&l开发者_如何学Got;diagnostic version="1.0">
  <!-- diagnostic panel 1 -->
  <panel xml:id="0">
    <!-- list controls -->
    <control xml:id="0_0">
      <settings description="text 1"/>
    </control>
    <control xml:id="0_1">
      <settings description="text 2"/>
    </control>
  </panel>
  <panel xml:id="1">
    <!-- list controls -->
    <control xml:id="1_0">
      <settings description="text 3"/>
    </control>
    <control xml:id="1_1">
      <settings description="text 4"/>
    </control>
  </panel>
</diagnostic>

and definition XPath:

//*[not(@description='-')]/@description

and Java code:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); 
domFactory.setNamespaceAware(true);  
DocumentBuilder builder = domFactory.newDocumentBuilder(); 
Document doc = builder.parse("diagnostic.xml"); 
XPath xpath = XPathFactory.newInstance().newXPath(); 
// XPath Query for showing all nodes value 
XPathExpression expr = xpath.compile("//*[not(@description='-')]/@description"); 

Object result = expr.evaluate(doc, XPathConstants.NODESET); 
NodeList nodes = (NodeList) result; 
for (int i = 0; i < nodes.getLength(); i++) { 
  System.out.println(i + ": " + nodes.item(i).getParentNode()  + nodes.item(i).getNodeValue());  
} 

This definition of XPath would return all attribute values ​​description where the value of this attribute is not '-'.

Output:

text 1
text 2
text 3
text 4

But I need to find this attribute description also attribute xml:id element control.

Output:

0_0 text 1
0_1 text 2
1_0 text 3
1_1 text 4

How to do that in my description also returns a xml:id element of control? I need to know that the description given element is control.


Someone correct me if I'm wrong, but I don't think this can be done with a single XPath expression. The concat function returns a single text result, not a list. I suggest you run multiple XPath expressions and construct your results from that, or run a single XPath expression to get the settings elements you need, then take the description attribute from it and concatenate it with the xml:id attribute from the parent element if that's a control one. Nodes keep references to their parents. Use method getParentNode() to obtain it.

Here's an alternative: run this XPath expression...

//control[settings[@description!='-']]/@xml:id | //control/settings[@description!='-']/@description

... and then concatenate the text of the alternating results in the returned node list. In other words, text from item 0 + item 1, text from item 2 + item 3 etc.

The above XPath expression will return this node list:

0_0
text 1
0_1
text 2
1_0
text 3
1_1
text 4

You can then parse through that list and construct your results.

Be careful. This will only work if there's at most 1 settings element per control element. Also, you may find that on evaluation the XPath engine throws an error for that xml: prefix. It may say that it's unknown. You might have to bind that prefix to the correct namespace first. Since the xml prefix is reserved and bound by default to a specific namespace, this might not be needed. I'm not certain as I haven't used it before.

I've tested the expression in XMLSpy. It's not entirely impossible that the XPath engine used in Java (or the one you set for use) returns the nodes in another order. It might evaluate both parts of the "or" (the pipe symbol) separately and then dump the results into a single node list. I don't know what the XPath spec mandates regarding result ordering.


I may be just as wrong, but the nodes you traverse in the result are the XML nodes themselves. Your code sample is almost there:
- nodes.item(i) points to the attribute "description".
- nodes.item(i).getParentNode() points to the tag "settings".
- nodes.item(i).getParentNode().getParentNode() would point to the tag "control" (class Element). You could then use getAttribute() or getAttributeNS() on that node to find get the attribute you need.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜