2009-12-31 10 views
7

У меня есть следующий код:Saxon XPath API возвращает TinyElementImpl вместо org.w3c.dom.Node

// 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); 

и это результат ...

 
class net.sf.saxon.tinytree.TinyElementImpl 
class java.util.ArrayList 
false 
false 

Просто чтобы прояснить , если я делаю это:

org.w3c.dom.Node node = (org.w3c.dom.Node)evaluate; 

или

org.w3c.dom.NodeList node = (org.w3c.dom.NodeList)evaluate2; 

Я получаю ClassCastException

Как это может быть? согласно Suns Java 1.5 API NODE и NodeSet следует сопоставить org.w3c.dom.Node и org.w3c.dom.NodeList соответственно

Просто clarify2 да я знаю, что узел является iterface, что GetClass() возвращает конкретный класс.

ответ

6

Хорошо, я понял!

Если метод оценки получает входной источник, возникает ошибка выше.

например.

InputSource someXML = new InputSource(new StringReader("<someXML>...</someXML>)"); 
Object result = expression.evaluate(someXML, XPathConstants.NODE); 
Node node = (Node) result; // ClassCastException 

Тогда результат не выполняет org.w3c.dom.Node (TinyElementImpl)

Но если оценивать получает 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 

Он работает, но до сих пор, это странно .. .

+0

Делает смысл .... если вы положите W3C DOM внутрь, вы получите W3C DOM. В противном случае вы получаете проприетарный DOM. – skaffman

+2

Добро пожаловать в Java XML. – Esko

2

Node - это интерфейс. У вас должен быть конкретный класс для реализации. И getClass() возвращает этот конкретный класс.

Редактировать в ответ на комментарий:

К сожалению, я не обратил внимание на InstanceOf. Рассматривая source code, оказывается, что TinyNodeImpl не реализует org.w3c.dom.Node. И, глядя на документы JDK, кажется, что этого не нужно: doc для javax.xml.XPath ссылается на XPathConstants для типа результата и относится к типу данных типа «XPath 1.0 NodeSet» (который, если вы посмотрите на спецификация XPath 1.0, не определена).

Таким образом, кажется, что возврат из API XPath требуется только для согласования при использовании в этом API. Я не уверен, что вы хотели услышать. Можете ли вы использовать встроенную реализацию JDK? Я знаю, что он возвращает org.w3c.dom объектов.

+0

Спасибо, I» уточню вопрос. И да, я получаю ClassCastException, вы можете сказать, что по последним двум строкам кода (оцените экземпляр Node), если он не является экземпляром, он не реализует этот интерфейс, поэтому будет выполняться класс cast exceptino. –

-1

kdgregory верна, что Node - это просто интерфейс, и TinyElementImpl реализует этот интерфейс. expression.evaluate() не может вернуть экземпляр Node, он должен вернуть конкретный класс, который реализует узел.

Это может быть полезно, чтобы указать на то, что вы можете использовать экземпляр TinyElementImplв в Node, и вы можете легко бросить экземпляры TinyElementImp в Node.

Например, это должно работать нормально:

Node result = (Node) expression.evaluate(someXML, XPathConstants.NODE); 

Вы можете использовать result путем вызова любого из методов Node, и передавая ее любым способом, который принимает Node.

+0

Пожалуйста, прочитайте комментарий на ответ kdgregory. TinyElementImpl, кстати, не реализует узел. –

+0

ОК, да, я вижу, что сделал неправильное предположение. Тем не менее, я думаю, что дух моего ответа затрагивает некоторые аспекты этого вопроса в честных попытках помочь. Я могу жить с нисходящим потоком. –

2

Немного странно, это одно. Saxon javadoc говорит, что TinyElementImpl не реализует ни один из интерфейсов org.w3c.dom, и все же вы возвращаете их из оценки XPath.

Я предполагаю, что Саксон избегает стандартной модели DOM в пользу своей собственной. Я подозреваю, что XPathConstants.NODE, который вы переходите на evaluate, на самом деле просто подсказка. Для выражений XPath разрешено возвращать любую старую вещь (например, Apache JXPath использует выражения XPath для запроса графиков Java-объектов), поэтому Saxon разрешает возвращать свои собственные типы DOM, а не org.w3c.

Решение: используйте саксонские типы DOM как возвращенные или не используйте Saxon.

3

Код:

Object evaluate = expression.evaluate(someXML, XPathConstants.NODE); 
System.out.println(evaluate instanceof Node); 
System.out.println(NodeOverNodeInfo.wrap((NodeInfo) evaluate) instanceof Node); 

Он печатает:

false 
true 

Возвращаемый объект типа NodeInfo, так что вам нужно обернуть его как реальный Node, так что вы можете получить доступ к его методам:

Node n = NodeOverNodeInfo.wrap((NodeInfo) evaluate); 
System.out.println(n.getNodeName()); 
System.out.println(n.getTextContent()); 
+0

Это работает и является наиболее полезным ответом на странице. Отлично сработано! –

 Смежные вопросы

  • Нет связанных вопросов^_^