Reputation: 887
I am having difficulty trying to parse an XML content with Xpath. Xml includes namespace information. I have tried to create a NameSpaceContextImp (apache WS commons implementations of NameSpaceContext interface in jdk) to map the namaspace prefixes to URIs, however couldn't successfully queried the xml document. When I use online xpath testing tool at http://chris.photobooks.com/xml/default.htm, the xpath query I use comes up with my expected nodes/elements. So I am trying to figure out what it is that I am doing wrong. I am providing the xml document and the sample code snippet. I would appreciate any feedback. As a note, I have tried xpath queries both with and without the namespace prefixes.
NamespaceContextImpl namespaceContext = new NamespaceContextImpl();
namespaceContext.startPrefixMapping("wsp", "http://schemas.xmlsoap.org/ws/2002/12/policy");
namespaceContext.startPrefixMapping("L7p", "http://www.layer7tech.com/ws/policy");
String policyXml = "xml content that is pasted below"
InputSource inputSource = new InputSource(new StringReader(policyXml));
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xPath = xpathFactory.newXPath();
xPath.setNamespaceContext(namespaceContext);
XPathExpression xpathExpression = xPath.compile("/wsp:Policy/wsp:All");
String evaluation = xpathExpression.evaluate(inputSource);
if (evaluation.trim().length() > 0) {
System.out.println(evaluation);
}
<?xml version="1.0" encoding="UTF-8"?>
<wsp:Policy xmlns:L7p="http://www.layer7tech.com/ws/policy" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsp:All wsp:Usage="Required">
<L7p:SetVariable>
<L7p:AssertionComment assertionComment="included">
<L7p:Properties mapValue="included">
<L7p:entry>
<L7p:key stringValue="RIGHT.COMMENT"/>
<L7p:value stringValue="Used to enable message logging, Null (allow MSGDEBUG Header to set level), 0 - default,1 - Medium,2 - Full"/>
</L7p:entry>
</L7p:Properties>
</L7p:AssertionComment>
<L7p:Base64Expression stringValue=""/>
<L7p:VariableToSet stringValue="LOCAL_POLICY_DEBUG_LEVEL"/>
</L7p:SetVariable>
<L7p:Include>
<L7p:PolicyGuid stringValue="ec1f4166-4299-4e44-bf9d-c5c2a9f0c894"/>
</L7p:Include>
<L7p:SslAssertion>
<L7p:Option optionValue="Optional"/>
</L7p:SslAssertion>
<wsp:OneOrMore L7p:Enabled="false" wsp:Usage="Required">
<L7p:SpecificUser>
<L7p:Enabled booleanValue="false"/>
<L7p:IdentityProviderOid longValue="-2"/>
<L7p:UserLogin stringValue="test"/>
<L7p:UserName stringValue="test"/>
<L7p:UserUid stringValue="58916874"/>
</L7p:SpecificUser>
<L7p:SpecificUser>
<L7p:Enabled booleanValue="false"/>
<L7p:IdentityProviderOid longValue="-2"/>
<L7p:UserLogin stringValue="test"/>
<L7p:UserName stringValue="test"/>
<L7p:UserUid stringValue="58916873"/>
</L7p:SpecificUser>
<L7p:SpecificUser>
<L7p:Enabled booleanValue="false"/>
<L7p:IdentityProviderOid longValue="-2"/>
<L7p:UserLogin stringValue="test"/>
<L7p:UserName stringValue="test"/>
<L7p:UserUid stringValue="58916876"/>
</L7p:SpecificUser>
<L7p:SpecificUser>
<L7p:Enabled booleanValue="false"/>
<L7p:IdentityProviderOid longValue="-2"/>
<L7p:UserLogin stringValue="test"/>
<L7p:UserName stringValue="test"/>
<L7p:UserUid stringValue="58916875"/>
</L7p:SpecificUser>
<L7p:SpecificUser>
<L7p:Enabled booleanValue="false"/>
<L7p:IdentityProviderOid longValue="-2"/>
<L7p:UserLogin stringValue="testengineering-user"/>
<L7p:UserName stringValue="testengineering-user"/>
<L7p:UserUid stringValue="48201728"/>
</L7p:SpecificUser>
</wsp:OneOrMore>
<wsp:OneOrMore wsp:Usage="Required">
<L7p:HttpRoutingAssertion>
<L7p:ProtectedServiceUrl stringValue="http://localhost:13000/Services/Finance/v1"/>
<L7p:RequestHeaderRules httpPassthroughRuleSet="included">
<L7p:Rules httpPassthroughRules="included">
<L7p:item httpPassthroughRule="included">
<L7p:Name stringValue="Cookie"/>
</L7p:item>
<L7p:item httpPassthroughRule="included">
<L7p:Name stringValue="SOAPAction"/>
</L7p:item>
</L7p:Rules>
</L7p:RequestHeaderRules>
<L7p:RequestParamRules httpPassthroughRuleSet="included">
<L7p:ForwardAll booleanValue="true"/>
<L7p:Rules httpPassthroughRules="included"/>
</L7p:RequestParamRules>
<L7p:ResponseHeaderRules httpPassthroughRuleSet="included">
<L7p:Rules httpPassthroughRules="included">
<L7p:item httpPassthroughRule="included">
<L7p:Name stringValue="Set-Cookie"/>
</L7p:item>
</L7p:Rules>
</L7p:ResponseHeaderRules>
</L7p:HttpRoutingAssertion>
<L7p:Include>
<L7p:PolicyGuid stringValue="b438384e-eeb0-45c5-8a7e-d30da78f07ee"/>
</L7p:Include>
</wsp:OneOrMore>
</wsp:All>
</wsp:Policy>
Upvotes: 1
Views: 461
Reputation: 163322
Calling evaluate() with one argument requests conversion of the result to a string, which is equivalent to taking the string value of the requested node: that is, the concatenation of the text node descendants of the selected element. Since all the descendant text nodes are whitespace, you will get nothing back.
For once, namespaces are not the issue.
Upvotes: 0
Reputation: 108879
The only CDATA under the All
element is whitespace, which you trim. If you want to get DOM elements, use the NODE or NODESET (NodeList
) options.
String xml = "<foo><bar baz='hello' /></foo>";
InputSource src = new InputSource(new StringReader(xml));
XPathExpression expr = XPathFactory.newInstance().newXPath()
.compile("/foo/bar");
Node node = (Node) expr.evaluate(src, XPathConstants.NODE);
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
trans.transform(new DOMSource(node), new StreamResult(System.out));
Upvotes: 1