[英]Saxon XPath API returns TinyElementImpl instead of org.w3c.dom.Node
I have the following code: 我有以下代码:
// xpath evaluates to net.sf.saxon.xpath.XPathEvaluator
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expression = xpath.compile("/foo/bar");
Object evaluate = expression.evaluate(someXML, XPathConstants.NODE);
Object evaluate2 = expression.evaluate(someXML, XPathConstants.NODESET);
System.out.println(evaluate!=null?evaluate.getClass():"null");
System.out.println(evaluate2!=null?evaluate2.getClass():"null2");
System.out.println(evaluate instanceof Node);
System.out.println(evaluate2 instanceof NodeList);
and this is the result... 这就是结果......
class net.sf.saxon.tinytree.TinyElementImpl class java.util.ArrayList false false
Just to clarify , if I do this: 只是为了澄清 ,如果我这样做:
org.w3c.dom.Node node = (org.w3c.dom.Node)evaluate;
or 要么
org.w3c.dom.NodeList node = (org.w3c.dom.NodeList)evaluate2;
I get a ClassCastException
我得到一个
ClassCastException
How can that be? 怎么可能? according to Suns Java 1.5 API NODE and NODESET should map to
org.w3c.dom.Node
and org.w3c.dom.NodeList
respectively 根据Suns Java 1.5 API NODE和NODESET应分别映射到
org.w3c.dom.Node
和org.w3c.dom.NodeList
Just to clarify2 yes I know Node is an iterface, that getClass() returns a concrete class. 只是澄清2是的我知道Node是一个iterface,getClass()返回一个具体的类。
Ok I figured it out! 好吧我明白了!
If the evaluate method receives an InputSource the above error occurs. 如果evaluate方法收到InputSource,则会发生上述错误。
eg 例如
InputSource someXML = new InputSource(new StringReader("<someXML>...</someXML>)");
Object result = expression.evaluate(someXML, XPathConstants.NODE);
Node node = (Node) result; // ClassCastException
Then result is not implementing org.w3c.dom.Node
( TinyElementImpl
) 然后结果没有实现
org.w3c.dom.Node
( TinyElementImpl
)
But if evaluate receives a Node
(or a Document
): 但是,如果evaluate接收
Node
(或Document
):
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
Document someXML = documentBuilder.parse(new InputSource(new StringReader("<someXML>...</someXML>)"));
Object result = expression.evaluate(someXML, XPathConstants.NODE);
Node node = (Node) result; // works
It works, but still, this is weird... 它有效,但仍然,这很奇怪......
Try this code: 试试这段代码:
Object evaluate = expression.evaluate(someXML, XPathConstants.NODE);
System.out.println(evaluate instanceof Node);
System.out.println(NodeOverNodeInfo.wrap((NodeInfo) evaluate) instanceof Node);
It prints: 它打印:
false
true
The returned object is of type NodeInfo
, so you need wrap it as a real Node
, so you can access its methods: 返回的对象是
NodeInfo
类型,因此您需要将其包装为真实Node
,以便可以访问其方法:
Node n = NodeOverNodeInfo.wrap((NodeInfo) evaluate);
System.out.println(n.getNodeName());
System.out.println(n.getTextContent());
Node
is an interface. Node
是一个接口。 You have to have a concrete class for implementation. 你必须有一个具体的实现类。 And
getClass()
returns that concrete class. 并且
getClass()
返回该具体类。
Edit in response to comment: 编辑以回应评论:
Sorry, I didn't pay attention to the instanceof. 对不起,我没注意instanceof。 Looking at the source code , it appears that
TinyNodeImpl
doesn't implement org.w3c.dom.Node
. 查看源代码 ,看起来
TinyNodeImpl
没有实现org.w3c.dom.Node
。 And looking at the JDK docs, it appears that it doesn't have to: the doc for javax.xml.XPath refers you to XPathConstants for the result type, and it refers to the "The XPath 1.0 NodeSet data type" (which, if you look at the XPath 1.0 spec, is not defined). 看一下JDK文档,它似乎没有: javax.xml.XPath的doc引用了结果类型的XPathConstants ,它引用了“XPath 1.0 NodeSet数据类型”(其中,如果你看看XPath 1.0规范,没有定义)。
So, it seems that returns from the XPath API are only required to be consistent when used within that API. 因此,似乎只有在该API中使用时,XPath API的返回才需要保持一致。 Not exactly what you wanted to hear, I'm sure.
我确定,不完全是你想听到的。 Can you use the built-in JDK implementation?
你能使用内置的JDK实现吗? I know that it returns
org.w3c.dom
objects. 我知道它会返回
org.w3c.dom
对象。
It's a bit odd, this one. 这个有点奇怪。 The Saxon javadoc says that
TinyElementImpl
doesn't implement any of the org.w3c.dom
interfaces, and yet you're getting them back from the XPath evaluation. Saxon javadoc说
TinyElementImpl
没有实现任何org.w3c.dom
接口,但是你从XPath评估中得到了它们。
My guess is that Saxon eschews the standard DOM model in favour of its own one. 我的猜测是,Saxon避开了标准的DOM模型,而选择了自己的模型。 I suspect that the
XPathConstants.NODE
that you pass to evaluate
is really just a hint. 我怀疑你传递给
evaluate
的XPathConstants.NODE
实际上只是一个提示。 It's permitted for XPath expressions to return any old thing (for example, Apache JXPath uses XPath expressions to query java objects graphs), so it's permitted for Saxon to return its own DOM types rather than org.w3c
standard ones. XPath表达式允许返回任何旧东西(例如, Apache JXPath使用XPath表达式来查询java对象图),因此Saxon允许返回自己的DOM类型而不是
org.w3c
标准类型。
Solution: either use the Saxon DOM types as returned, or don't use Saxon. 解决方案:要么使用返回的Saxon DOM类型,要么不使用Saxon。
kdgregory is correct that Node
is just an interface, and TinyElementImpl
implements that interface. kdgregory是正确的,
Node
只是一个接口,而TinyElementImpl
实现了该接口。 expression.evaluate()
can't return an instance of Node
, it has to return a concrete class which implements node. expression.evaluate()
不能返回Node
的实例,它必须返回一个实现 node的具体类。
It might be useful to point out that you can use an instance of TinyElementImpl
as as Node
, and you can easily cast instances of TinyElementImp
to Node
. 这可能是要指出,你可以使用的实例有用
TinyElementImpl
如为Node
,您可以轻松地投的实例TinyElementImp
到Node
。
For example, this should work just fine: 例如,这应该工作得很好:
Node result = (Node) expression.evaluate(someXML, XPathConstants.NODE);
You can then use result
by calling any of the methods of Node
, and by passing it to any method which accepts a Node
. 然后,您可以通过调用
Node
任何方法来使用result
,并将其传递给任何接受Node
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.