【问题标题】:Saxon: convert xdmNode to org.w3c.dom.Node撒克逊人:将 xdmNode 转换为 org.w3c.dom.Node
【发布时间】:2023-03-25 20:17:01
【问题描述】:

我想将 xdmNode 转换为 dom 节点。我找到了以下部分解决方案:

Processor proc = new Processor(false);
XPathCompiler xpath = proc.newXPathCompiler();
Document doc = DocumentUtilities.createEventCountsTestDocument();
XdmNode xdmNode = proc.newDocumentBuilder().wrap(doc);

expression = "/caseFileModel/EventCount/EventCountEvents[EventCmmnId=\"_4cd9cdaabbd244548a32afcd4cf2e1c0\" and EventEventType=\"CREATE\"]/Timestamps/Date[last()]";
value = xpath.evaluate(expression, xdmNode);
XdmNode node = (XdmNode) value;
Node element = ((Node) node.getExternalNode());
System.out.println(element.getTextContent());

其中createEventCountsTestDocument 根据以下 XML 生成文档:

<caseFileModel>
        </EventCountEvents>
        <EventCountEvents>
            <EventCmmnId>_8dbe1b3fa1a04787b2ef35d153d93ae5</EventCmmnId>
            <EventEventType>CREATE</EventEventType>
            <EventCount>1</EventCount>
            <Timestamps>
                <Date>2017-03-13T16:47:04Z</Date>
            </Timestamps>
        </EventCountEvents>
        <EventCountEvents>
            <EventCmmnId>_4cd9cdaabbd244548a32afcd4cf2e1c0</EventCmmnId>
            <EventEventType>CREATE</EventEventType>
            <EventCount>1</EventCount>
            <Timestamps>
                <Date>2017-03-13T16:47:04Z</Date>
            </Timestamps>
        </EventCountEvents>
    </EventCount>
</caseFileModel>

我得到了正确的输出,即2017-03-03T12:00:00Z,但是elementcom.sun.org.apache.xerces.internal.dom.DeferredElementImpl 而不是w3c.dom.Node。这意味着当我调用element.getNodeValue() 时,它会返回null。如果我调用element.getFirstChild().getNodeValue(),它会返回正确的值2017-03-03T12:00:00Z。所以似乎有什么问题,但我找不到。我想找到一种将xdmNode 转换为w3c.dom.Node 而不是DeferredElementImpl 的方法。

【问题讨论】:

  • 我不明白问题出在哪里,DOM w3.org/TR/DOM-Level-3-Core/core.html#ID-F68D080 将元素节点的节点值定义为 null 以便您得到正确的结果。 Nodecom.sun.org.apache.xerces.internal.dom.DeferredElementImpl实现的接口,不知道你想要什么样的结果。如果你想要一个基于类的对象模型,那么在 Java 世界中使用 JDOM 或 XOM,根据定义,DOM 提供了由类实现的接口。

标签: java dom xpath saxon xpath-2.0


【解决方案1】:

这里有几点。恐怕这是一个相当复杂的故事。

Saxon 有两个表示节点的接口:一个高级接口XdmNode 和一个低级接口NodeInfoXdmNode 始终是 NodeInfo 的包装器。

NodeInfo 有很多不同的实现。 Saxon 中有两个“本地”实现,分别用于 TinyTree 和 LinkedTree 模型;也有包装外部节点模型的实现,包括 DOM、JDOM、DOM4J、XOM 和 AXIOM。

如果您开始使用的XdmNode 是一个围绕NodeInfo 的包装器,该NodeInfo 本身包装了一个DOM Node,那么您可以使用XdmNode.getExternalNode() 访问底层DOM 节点。这个方法的签名返回Object:这是因为被包裹的节点可能是DOM,也可能是JDOM、XOM等等。

以上段落描述了您当前正在做的事情。您不必担心结果是com.sun.org.apache.xerces.internal.dom.DeferredElementImpl 的实例;这只是实现org.w3c.dom.Node 接口的众多内部类之一。

如果您开始的 XdmNode 不是 DOM Node 的包装器,那么您有两种选择:

  1. 您可以将底层NodeInfo 包装在NodeOverNodeInfo 类的实例中,该类提供底层NodeInfo 节点的DOM 视图。但是,这是一个只读视图,因为撒克逊节点(通常)是不可变的。

  2. 您可以将 Saxon 节点复制到 DOM 节点,最好通过身份转换来完成。

在所有这些中,您应该知道 Saxon 在处理 DOM 树时通常比处理其自己的内部树模型时慢 5 倍。这主要是由于在 DOM 中处理名称和命名空间的方式效率低下。

此外,正如您所发现的,用于 element.getNodeValue() 之类的 DOM 方法并不总是如您所愿。我个人避免 DOM 像瘟疫一样。

【讨论】:

    猜你喜欢
    • 2019-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多