саксонские различные значения выдают исключение

Я пытаюсь запустить XPath с «различными значениями», используя Saxon. Вот мой код:

 @Test
public void testAttributeSelect() throws XPathFactoryConfigurationException {
     System.setProperty("javax.xml.xpath.XPathFactory:"
     + NamespaceConstant.OBJECT_MODEL_SAXON,
     "net.sf.saxon.xpath.XPathFactoryImpl");
      System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
    "net.sf.saxon.dom.DocumentBuilderFactoryImpl");
      String xpathString = "distinct-values(//id)";
    DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();

    domFactory.setNamespaceAware(true);

    try {
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        System.out.println(builder.getClass());
        Document doc =
       builder.parse(this.getClass().getResourceAsStream("parametrizedId_feed.xml"));
        System.out.println(doc.getClass());
        XPath xpath =
      XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON).newXPath();

        NodeList s1 = (NodeList) 
        xpath.evaluate("/matches", doc, XPathConstants.NODESET);
       NodeList s = (NodeList) 
       xpath.evaluate(xpathString, s1 , XPathConstants.NODESET);

Я получаю это исключение:

javax.xml.xpath.XPathExpressionException: не удается найти реализацию объектной модели для узлов класса net.sf.saxon.dom.DOMNodeList в net.sf.saxon.xpath.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:300) в net.sf .saxon.xpath.XPathEvaluator.evaluate(XPathEvaluator.java:434) в ca.cbc.panacea.playground.TestXpath.testAttributeSelect(TestXpath.java:43) в sun.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) в sun.reflect .NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

Файл jar Saxon-dom находится в пути к классам. Кроме того, если я попытаюсь вызвать «различные значения» непосредственно в объекте документа, я получу:

net.sf.saxon.trans.XPathException: для функции расширения требуется класс org.w3c.dom.NodeList; предоставленное значение класса net.sf.saxon.value.UntypedAtomicValue не может быть преобразовано в net.sf.saxon.dom.DOMObjectModel.convertXPathValueToObject(DOMObjectModel.java:395) в net.sf.saxon.dom.DOMObjectModel.access$000( DOMObjectModel.java:42) по адресу net.sf.saxon.dom.DOMObjectModel$5.convert(DOMObjectModel.java:166) по адресу net.sf.saxon.xpath.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:352) по адресу net.sf. saxon.xpath.XPathEvaluator.evaluate(XPathEvaluator.java:434)

Я не могу понять, что здесь происходит. И гугл тоже нет!


person Arash    schedule 08.11.2011    source источник


Ответы (3)


Первое, на что стоит обратить внимание, это то, что DOM и Saxon не особенно хорошо сочетаются друг с другом. Если вы строите дерево, чтобы использовать на нем Saxon, используйте родную модель дерева Saxon вместо DOM — это в десять раз быстрее.

Тот факт, что вы упомянули saxon-dom.jar, означает, что вы используете довольно старую версию Saxon, возможно, ту, которая больше не поддерживается. Поэтому моим следующим предложением было бы перейти к более позднему выпуску.

Еще я заметил, что вы попросили процессор XPath для работы с объектной моделью Saxon, а затем используете его для работы с объектной моделью DOM. Я не знаю, сработает это или нет. (Если вы хотите быть уверены в загрузке Saxon, а не какого-либо другого механизма XPath, например, потому что вам нужен XPath 2.0, то лучше полностью пропустить механизмы фабрики JAXP и просто создать экземпляр реализации Saxon напрямую.)

person Michael Kay    schedule 08.11.2011
comment
@arash: Чтобы увидеть примеры кода, один для использования собственного дерева Saxon и один для использования DOM, перейдите на sourceforge.net/projects/saxon/files/Saxon-HE/9.4, затем загрузите файл ресурсов Saxon. Найдите в папке examples/java файлы XPathExample.java и XPathExampleDOM.java. Эти образцы помогают увидеть разницу. - person james.garriss; 20.04.2012

Я нашел решение для получения NodeList от Saxon. После выполнения инструкции «List s = (List) xpath.evaluate(xpathString, doc1, XPathConstants.NODESET);» вы можете использовать приведенный ниже код, чтобы прочитать узел и значение узла из списка:

getTagValue("COMMODITYNAME", NodeOverNodeInfo.wrap((NodeInfo) s.get(i))) "COMMODITYNAME" — это узел в XML, значение которого вы хотите прочитать, и NodeOverNodeInfo.wrap((NodeInfo) s.get(i) ) — это узел, в настоящее время указывающий из списка «s».

private String getTagValue (строка strag, NodeOverNodeInfo nodeInfo) {

    NodeList nodeList = nodeInfo.getChildNodes(); //list of  XML node
    Node nodeValue = null;
    String strReturn = null;
    for (int iItem=0;iItem<nodeList.getLength();iItem++)
    {
        nodeValue = nodeList.item(iItem).getFirstChild();   
        if (nodeValue != null && strag.equalsIgnoreCase(nodeValue.getParentNode().getNodeName()))
        {
            strReturn = nodeValue.getNodeValue();
            //punta la tag index
            //System.out.println(nodeValue.getParentNode().getNodeName()); //this is the node name
            //System.out.println(nodeValue.getNodeValue()); // this is the node value
        }
    }
return strReturn;
}

До свидания, Валерио

person derossiv    schedule 27.03.2014

Это не ответ, я просто хотел прокомментировать ответ Майкла, но комментарии очень ограничены. Спасибо за ответ Михаил. Мои зависимости следующие:

<dependency>
        <groupId>net.sourceforge.saxon</groupId>
        <artifactId>saxon</artifactId>
        <version>9.1.0.8</version>
    </dependency>
    <dependency>
        <groupId>net.sourceforge.saxon</groupId>
        <artifactId>saxon</artifactId>
        <version>9.1.0.8</version>
        <classifier>xpath</classifier>
    </dependency>

    <dependency>
    <groupId>net.sourceforge.saxon</groupId>
        <artifactId>saxon</artifactId>
        <version>9.1.0.8</version>
        <classifier>dom</classifier>
    </dependency>

Насколько я знаю, это последняя версия репозитория maven. Пожалуйста, дайте мне знать, если я что-то пропущу здесь. Ваше объяснение ситуации было очень хорошим, за исключением того, что мне нужен пример кода, чтобы понять, как все это сделать. Я сделал следующие изменения, и это сработало!

InputSource is = new InputSource(this.getClass().getResourceAsStream("parametrizedId_feed.xml"));
         SAXSource ss = new SAXSource(is);

        XPath xpath =  XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON).newXPath();
        NodeInfo doc1 = ((XPathEvaluator)xpath).setSource(ss);
        System.out.println("Loaded XPath Provider " + xpath.getClass().getName());

       List s = (List) xpath.evaluate(xpathString, doc1 , XPathConstants.NODESET);
        for(int i = 0 ; i<s.size(); i++){
            String n = (String) s.get(i);
            System.out.println(n);

        }

Это то, что вы имели в виду под моделью саксонского дерева? Единственная проблема заключается в том, что метод оценки возвращает список вместо списка узлов. Я хочу упомянуть, что мы перешли на Saxon из-за превосходной скорости и лучшей функциональности, поэтому кодовая база имеет много зависимостей от JAXP API, от которых просто невозможно избавиться.

person Arash    schedule 08.11.2011
comment
Любая версия Saxon, которую вы найдете в репозитории Maven, является неофициальной и неавторизованной и, вероятно, не содержит официальных уведомлений, которые требуются в соответствии с условиями лицензирования для сторонних компонентов, таких как библиотека Unicode. Текущая версия Saxon 9.4. Да, NodeInfo — это узел в модели дерева Saxon. Класс NodeList специфичен для DOM, и вы получите обратно NodeList, только если обрабатываете DOM. (Боюсь, что спецификация JAXP очень запутана при обработке моделей, отличных от DOM, и я бы предпочел Saxon s9api API.) - person Michael Kay; 19.12.2011