【问题标题】:Java code using Xerces's getElementsByTagName does not return child node使用 Xerces 的 getElementsByTagName 的 Java 代码不返回子节点
【发布时间】:2014-04-30 14:03:42
【问题描述】:

我正在使用 Xerces 解析器来尝试解析以下 XML sn-p。当我使用 findElementsByTagName 方法查找 Circle 时,我可以找到“位置信息”元素,我得到一个空的 NodeList。有人可以抽查一下,看看我做错了什么吗?

<urn:locationResponse xmlns:urn="urn:ietf:params:xml:ns:geopriv:held">
<presence entity="pres:www.telecomsys.com" xmlns="urn:ietf:params:xml:ns:pidf"
          xmlns:gp="urn:ietf:params:xml:ns:pidf:geopriv10" xmlns:dm="urn:ietf:params:xml:ns:pidf:data-model"
          xmlns:gs="http://www.opengis.net/pidflo/1.0" xmlns:ca="urn:ietf:params:xml:ns:pidf:geopriv10:civicAddr"
          xmlns:gml="http://www.opengis.net/gml">
    <tuple id="FIRST_LOCATION">
        <status>
            <gp:geopriv>
                <location-info xmlns="urn:ietf:params:xml:ns:pidf:geopriv10">
                    <gs:Circle srsName="urn:ogc:def:crs:EPSG::4326">
                        <gml:pos>00.000000 -00.00000</gml:pos>
                        <gs:radius uom="urn:ogc:def:uom:EPSG::9001">200</gs:radius>
                    </gs:Circle>
                    <gp:confidence>95</gp:confidence>
                </location-info>
                <gp:usage-rules>
                    <gp:retransmission-allowed>yes</gp:retransmission-allowed>
                </gp:usage-rules>
                <gp:method>Derived</gp:method>
            </gp:geopriv>
        </status>
        <timestamp>2001-01-00T00:00Z</timestamp>
    </tuple>
</presence>

以下是我的代码,它试图从这个 XML 中获取“Circle”标签

    private static final Log logger = LogFactory.getLog(PIDFLOParser.class);
    private static final String LOCATION_INFO = "location-info";
    private static final String CIRCLE = "Circle";

    // Use of the Document BuilderFactory to create a DocumentBuilder class.
    DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = fact.newDocumentBuilder();

    Document doc = builder.parse(new InputSource(new StringReader(xmlDoc)));
    doc.getDocumentElement().normalize();

    Node node = doc.getDocumentElement();

    String root = node.getNodeName();
    System.out.println("Root Node: " + root);

    NodeList listResponse = doc.getElementsByTagName(LOCATION_INFO);
    if (listResponse.getLength() == 0) {
        System.out.println(String.format("%s doesn't exist in the Document.", LOCATION_INFO));
    }

    Node firstNode = listResponse.item(0);
    listResponse = ((Element) firstNode).getElementsByTagName(CIRCLE);
    if (listResponse.getLength() == 0) {
        System.out.println(String.format("%s doesn't exist in the Document.", CIRCLE));
    }

    listResponse = ((Element) firstNode).getElementsByTagNameNS("gs", CIRCLE);
    if (listResponse.getLength() == 0) {
        System.out.println(String.format("%s doesn't exist in the Document when searching with namespace.", CIRCLE));
    }

这段代码的输出是:

    Root Node: urn:locationResponse
Circle doesn't exist in the Document.
Circle doesn't exist in the Document when searching with namespace.

我做错了什么?提前感谢您的帮助!

在 guido 关于命名空间的完整 URI 的评论后更新

...
    private static final String NS_GS = "http://www.opengis.net/pidflo/1.0";
...
    listResponse = ((Element) firstNode).getElementsByTagNameNS(NS_GS, CIRCLE);
    if (listResponse.getLength() == 0) {
        System.out.println(String.format("%s doesn't exist in the Document when searching with namespace.", CIRCLE));
    }

输出还是一样的:

Root Node: urn:locationResponse
Circle doesn't exist in the Document.
Circle doesn't exist in the Document when searching with namespace.

【问题讨论】:

  • 您在代码中哪里使用了findElementByTagName()
  • 您需要在 getElementsByTagName 调用中指定命名空间 URI
  • 谢谢布拉杰。我更正了标题
  • 谢谢吉多。第一种方法(getElementsByTagName)在查找位置信息时不需要命名空间,但是在尝试获取 Circle 时,这两种方法都不起作用。我的代码示例和输出显示两者都找不到元素
  • @user3589431 您需要使用 URI 而不是命名空间文字

标签: java xml xerces


【解决方案1】:

当您调用getElementsByTagNameNS 时,您应该指定命名空间的 URI,而不是 xml 中使用的前缀,因此:

getElementsByTagNameNS("gs", CIRCLE);

应该是:

getElementsByTagNameNS("http://www.opengis.net/pidflo/1.0", CIRCLE);

因为gs:Circle元素是在命名空间URI下定义的:

xmlns:gs="http://www.opengis.net/pidflo/1.0"

要使命名空间工作,您需要为其设置工厂:

 DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
 fact.setNamespaceAware(true);

或者,您可以只使用(不带命名空间)完整的限定名称:

 getElementsByTagName("gs:Circle");

注意:另请注意,您的 xml 在您的问题中无效,因为它缺少结束根元素 &lt;/urn:locationResponse&gt;

【讨论】:

  • 好的...所以我不知道如何在 cmets 中放置换行符。 @guido,我正在更新原始代码块中的代码,但是根据您建议的更改,我仍然无法使其正常工作。请参阅上面的更新代码。
  • 谢谢@guido。将工厂设置为命名空间感知 (fact.setNamespaceAware(true)) 有效。另外,我发誓我使用标签名称“gs:Circle”进行了测试,但它没有用。但是,我现在尝试了,这也有效。所以谢谢!
猜你喜欢
  • 2011-03-19
  • 2019-03-04
  • 2013-09-20
  • 1970-01-01
  • 2021-01-14
  • 2017-04-12
  • 2016-05-07
  • 1970-01-01
  • 2012-06-03
相关资源
最近更新 更多