【发布时间】:2016-08-22 14:47:50
【问题描述】:
我正在从事一个迄今为止依赖于设置的项目:
DocumentBuilderFactory.setNamespaceAware(false);
实现命名空间灵活的 xpath(忽略可能传入的任何前缀)。
这仅在过去有效,因为正在使用 xalan 转换器,虽然从技术上讲,将命名空间感知设置为 false 的行为充其量应该是未定义的,但对于给定的 xml,xalan 将以下 xpath 视为有效。
xml:
<t:GiftBasket xmlns:t="http://tastyTreats.com/giftbasket">
<t:Fruit>
<t:Apple>
<t:Name>Cameo</t:Name>
<t:Color>Red</t:Color>
<t:TasteDescription>Juicy, crisp, and sweet with just a touch of tart, the Cameo is thought to come from both the Red and the Yellow Delicious.</t:TasteDescription>
</t:Apple>
<t:Apple>
<t:Name>Empire</t:Name>
<t:Color>Red</t:Color>
<t:TasteDescription>The interior is crisp and creamy white while being firmer than the McIntosh, so it makes for a good cooking apple. </t:TasteDescription>
</t:Apple>
<t:Apple>
<t:Name>Granny Smith</t:Name>
<t:Color>Green</t:Color>
<t:TasteDescription>Hard feel, crisp bite, and extremely tart taste. Some prefer to cook it, which sweetens it up.</t:TasteDescription>
</t:Apple>
</t:Fruit>
<t:Candy>
<t:Chocolate>Dark</t:Chocolate>
</t:Candy>
</t:GiftBasket>
xpath:
/GiftBasket/Fruit/Apple[Color='Red'][contains(TasteDescription,'sweet')]
在切换到 xslt 2.0 时,我切换到了 Saxon-HE 变压器。撒克逊人是一个更精确的变压器(好东西 IMO)。它认识到这些 xpath 表达式是“错误的”,我现在必须修复一堆像上面这样的 xpath 表达式才能工作,而不管引用的命名空间前缀是什么(客户端可以选择将 URI http://tastyTreats.com/giftbasket 前缀为“fluffybunnies”,据我所知)
我收到了其他很好的建议 here 关于如何利用 local-name() 功能来实现我需要的大部分内容。我的 xpath 现在显示为:
/*[local-name()='GiftBasket']/*[local-name()='Fruit']/*[local-name()='Apple'][Color='Red'][contains(TasteDescription,'sweet')]
然而,这仍然不准确,因为谓词中引用的元素仍然引用确切的元素名称Color 和TasteDescription,而没有命名空间灵活。有没有更好的方法来为所有口味描述中包含“甜”的红苹果编写 xpath,同时保持命名空间前缀的灵活性?
【问题讨论】:
-
输入 XML 中使用的前缀对于您的 XPath 表达式根本不重要,重要的是使用的命名空间 URI。假设它是恒定的并且在 Saxon 中是已知的,您可以将其设置为 XPath 的默认命名空间,并且可以像以前一样使用
/GiftBasket/Fruit/Apple[Color='Red'][contains(TasteDescription,'sweet')]。您如何设置默认命名空间取决于您使用的 Java API,因此您需要告诉我们您是继续使用 JAXP API 还是已切换到 Saxon s9api。 -
我通过调用 javax.xml.parsers.DocumentBuilderFactory.parse(is) 将文件中的 xml 读取到 InputSource 中,然后将其转换为 org.w3c.dom.Document。然后我通过调用 javax.xml.xpath.XPathFactory.newInstance().newXPath() 分别实例化一个 javax.xml.xpath.XPath。最后,我使用 xpath.evaluate(expression, document, javax.xml.xpath.XPathConstants.NODESET) 评估表达式并询问生成的 org.w3c.dom.NodeList.getLength() > 0。我没有看到对JAXP 或撒克逊 s9api。我怎样才能知道正在使用哪个?
-
查看答案,我认为将那里显示的代码应用于您的
xpath对象就足够了。 -
我做了一个调试会话来验证,抱歉所有的问题。正在使用的具体 xpath 评估器类是:net.sf.saxon.xpath.XPathEvaluator 而该类引用类型为 et.sf.saxon.xpath.JAXPXPathStaticContext 的上下文,所以我假设你的答案是正确的。我会试一试,感谢大家的牵手。
标签: xpath xml-namespaces