gpt4 book ai didi

java - Java MAVEN 示例中的 XpathException 表达式使用未绑定(bind)的命名空间前缀

转载 作者:行者123 更新时间:2023-12-01 08:53:35 26 4
gpt4 key购买 nike

经过谷歌研究后,我还没有找到有效的解决方案。“MAVEN by Example”电子书使用雅虎天气示例。不幸的是,雅虎似乎改变了他们的界面。我尝试为此调整 java 代码,但出现了这个恼人的异常:

        exec-maven-plugin:1.5.0:java
Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.5.0:java
Caused by: org.dom4j.XPathException:
Exception occurred evaluting XPath: /query/results/channel/yweather:location/@city.
Exception: XPath expression uses unbound namespace prefix yweather

xml 行本身是:

<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="1" yahoo:created="2017-02-13T10:57:34Z" yahoo:lang="en-US">
<results>
<channel>
...
<yweather:location xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" city="Theale" country="United Kingdom" region=" England"/>

整个 XML 可以从以下位置生成:

https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%3D91731537

我的代码(根据“MAVEN By Examples”电子书,针对更改后的 Yahoo 修改了 xpath 和 url):

    public Weather parse(InputStream inputStream) throws Exception {
Weather weather = new Weather();

SAXReader xmlReader = createXmlReader();
Document doc = xmlReader.read( inputStream );
weather.setCity(doc.valueOf ("//yweather:location/@city") );
// and several more, such as setCountry, setTemp
}

(我不是 xpath 专家,所以我尝试了

/query/results/channel/item/yweather:location/@city

同样,以防万一,结果相同。

xmlReader:

public InputStream retrieve(String woeid) throws Exception {
String url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%3D"+woeid; // eg 91731537
URLConnection conn = new URL(url).openConnection();
return conn.getInputStream();
}

天气类只是一组 getter 和 setter

当我在 this 中尝试此操作时XML 测试器,它工作得很好,但这可能是 XPATH-v2 与 Java v1 的效果。

最佳答案

当您评估 XPath //yweather:location/@city 时,XPath 处理器不知道 yweather 前缀绑定(bind)到哪个命名空间。您需要提供该信息。现在,您可能会认为“信息就在文档中!”你是对的。但前缀只是实际 namespace 的一种替代(如变量)。命名空间可以绑定(bind)到任何遵循前缀命名规则的前缀,也可以绑定(bind)到多个前缀。就像Java中引用对象的变量名本身并不重要,多个变量可以引用同一个对象。

例如,如果您使用 XPath //yw:location/@city 并将前缀 yw 绑定(bind)到命名空间 http://xml.weather。 yahoo.com/ns/rss/1.0,它仍然可以正常工作。

我建议您使用类org.dom4j.xpath.DefaultXPath而不是调用valueOf。创建它的实例并初始化命名空间上下文。有一个方法setNamespaceURIs that takes a Map from prefixes to namespaces并让您进行绑定(bind)。将上面的天气命名空间(实际的 URI)绑定(bind)到您选择的某个前缀(可能是 yweather,但也可以是您想要在实际 XPath 表达式中使用的任何其他前缀),然后使用该实例在文档中对其进行评估。

这是我对一些问题的回答,更深入地了解了命名空间及其前缀的真正含义:https://stackoverflow.com/a/8231272/630136

编辑:您使用的在线 XPath 测试器可能会执行一些幕后操作,从给定文档中提取 namespace 及其前缀,并将它们绑定(bind)到 XPath 处理器中。

如果您查看他们的示例 XML 并像这样调整它......

<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
<actors>
<actor id="1">Christian Bale</actor>
<actor id="2">Liam Neeson</actor>
<actor id="3">Michael Caine</actor>
</actors>
<foo:singers xmlns:test="http://www.foo.org/">
<test:singer id="4">Tom Waits</test:singer>
<foo:singer id="5">B.B. King</foo:singer>
<foo:singer id="6">Ray Charles</foo:singer>
</foo:singers>
</root>

XML 在语义上是等效的,因为 test 前缀绑定(bind)到与 foo 相同的命名空间。 XPath //foo:singer/@id 仍然返回所有正确的结果,因此该工具对此很聪明。然而,它不知道如何处理 XML...

<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
<actors>
<foo:actor id="1">Christian Bale</foo:actor>
<actor id="2">Liam Neeson</actor>
<actor id="3">Michael Caine</actor>
</actors>
<foo:singers xmlns:test="http://www.foo.org/" xmlns:foo="http://www.bar.org">
<test:singer id="4">Tom Waits</test:singer>
<foo:singer id="5">B.B. King</foo:singer>
<foo:singer id="6">Ray Charles</foo:singer>
</foo:singers>
</root>

和 XPath //foo:*/@id。前缀 foo 绑定(bind)到歌手元素范围中的不同命名空间,现在它只返回 id 5 和 6。与此 XPath 对比,它不使用前缀,而是使用命名空间- uri() 函数://*[namespace-uri()='http://www.foo.org/']/@id

正如预期的那样,最后一个返回 id 1 和 4。

关于java - Java MAVEN 示例中的 XpathException 表达式使用未绑定(bind)的命名空间前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42205027/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com