Reputation: 27286
I have the following XML instance:
<entities>
<person>
James
</person>
<legalEntity legalName="ACME">
</legalEntity>
<criminalOrganization>
<organizationName>Mafia</organizationName>
</criminalOrganization>
</entities>
And wish to produce a print-out with the type and name of each entity.
type is simply the element name (person
, legalEntity
or criminalOrganization
),
name is defined differently according to the kind of entity.
So I have the following code:
XPathExpression expr = xpath.compile("/entities/(person|legalEntity|criminalOrganization)");
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0 ; i < nodes.getLength() ; i++) {
Node node = nodes.item(i);
String nodeName = node.getNodeName();
XPathExpression exprInner = xpath.compile("text()|@legalName|organizationName/text()");
String name = (String) exprInner.evaluate(node);
System.out.printf("node type = %s, name = %s\n", nodeName, name);
}
The code produces the output:
node type = person, name =
James
node type = legalEntity, name = ACME
node type = criminalOrganization, name =
So basically, the name of person
entities is fetched OK (I just have to trim it), the name of legalEntity
is also fetched properly, but the name of criminalOrganization
is not.
Upon investigation I discovered that this is due to the fact that the first expression in the XPath union
structure: text()|@legalName|organizationName/text()
also evaluates (I suppose to some empty string value) in the case of criminalOrganization
so it is returned as the evaluated value of the entire union expression (rather than the last component organizationName/text()
).
My questions are:
why does this mixup not happen also in the case of legalEntity
?
how do I include element name predicates in the union
XPath expression to ensure that each component evaluates only for the intended type. I.e. text()
for person
elements, @legalName
for legalEntity
elements and organizationName/text()
for criminalOrganization
elements ?
Upvotes: 0
Views: 648
Reputation: 9627
In my opinion your solution is somehow a little bit strange but you may try to use self::
.
Try this (not tested):
XPathExpression exprInner
= xpath.compile("self::person/text()|
self::legalEntity/@legalName|
self::criminalOrganization/organizationName/text()");
Upvotes: 1