2016-08-11 9 views
0

Я новичок в Саксонии.Saxon HE 9.7 Результаты XQuery и существующий документ

В моем приложении java у меня есть требование о том, что мне нужно XQuery существующий документ dom4j. XQuery это заказать несколько элементов в порядке убывания по SerialNo:

<?xml version="1.0" encoding="UTF-8"?> 
<dataOfBooks:DataOfBooks xmlns:dataOfBooks="DataOfBooks"> 
    <Id>ID123</Id> 
    <books> 
    <book> 
     <name>ccc</name> 
     <serialNo>77</serialNo> 
    </book> 
    <book> 
     <name>aaa</name> 
     <serialNo>99</serialNo> 
    </book> 
    </books> 
</dataOfBooks:DataOfBooks> 

После того, как я получаю результаты XQuery, мне нужно, чтобы добавить их обратно к выше существующему документу. Я попытался использовать net.sf.saxon.s9api. Мне удалось вернуть результаты XQuery, как показано ниже:

<?xml version="1.0" encoding="UTF-8"?> 
<result:sequence 
    xmlns:result="http://saxon.sf.net/xquery-results" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <result:element> 
    <book xmlns:data="dataOfBooks"> 
     <name>aaa</name> 
     <serialNo>99</serialNo> 
    </book> 
    <book xmlns:data="dataOfBooks"> 
     <name>aaa</name> 
     <serialNo>77</serialNo> 
    </book> 
    </result:element> 
</result:sequence> 

Но у меня есть две проблемы. 1) результат имеет пространства имен и лишние вещи, которые я не хочу. 2) Мне не очень понятно, какой Saxon API использовать для добавления результатов XQuery в существующий документ. Так что результирующий документ выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?> 
<dataOfBooks:DataOfBooks xmlns:dataOfBooks="DataOfBooks"> 
    <Id>ID123</Id> 
    <books> 
    <book> 
     <name>aaa</name> 
     <serialNo>99</serialNo> 
    </book> 
    <book> 
     <name>ccc</name> 
     <serialNo>77</serialNo> 
    </book> 
    </books> 
</dataOfBooks:DataOfBooks> 

Еще один вопрос - я попытался с помощью dynamicContext и treeinfo классов, так как я, хотя использование treeinfo API может быть более оптимальным, но не повезло. Если вы считаете, использование TreeInfo API является эффективным, я очень ценю пример кода для моего требования. Ваша помощь очень ценится.

Заранее благодарим за ваше время и интерес.

+1

Если вы предоставляете информацию о запросе, мы можем сказать вам, где вы пошли не так, и если вы поставляете детали вашего кода Java, то мы можем предложить усовершенствования. –

ответ

1

Тот факт, что ваш код XQuery создает нежелательные пространства имен, объясняется тем, что ваш запрос неверен, но мы не можем сказать вам, как это неправильно, если вы не покажете нам код.

В вашем выпуске result:sequence показано, что вы каким-то образом умудрились запросить вывод в «завернутом» формате, что говорит о некотором злоупотреблении саксонскими API. Опять же, не видя своего кода, мы не можем точно сказать, что вы сделали неправильно.

Чтобы внести небольшие изменения в существующий документ, оставив без изменений, я обычно рекомендую XSLT над XQuery. В XSLT 3.0, вы можете сортировать книги по названию, используя следующую таблицу стилей:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="3.0"> 

<xsl:mode on-no-match="shallow-copy"/> 

<xsl:template match="books"> 
    <xsl:copy> 
    <xsl:perform-sort select="book"> 
     <xsl:sort select="name"/> 
    </xsl:perform-sort> 
    </xsl:copy> 
</xsl:template> 

</xsl:transform> 

В обоих XQuery и XSLT, результат вашего запроса/преобразование представляет собой новый документ, который вы можете использовать вместо оригинала , Если вы хотите сделать обновления на месте существующего документа, вы можете сделать это с помощью XQuery Update; однако Saxon не поддерживает обновление XQuery против документов в формате DOM4J.

Saxon позволяет вам отображать результат запроса или преобразования в виде документа DOM4J, и вы можете использовать API DOM4J, чтобы перенести этот документ (вернее, его внешний элемент) обратно в исходный документ DOM4J.

Позже

Теперь вы предоставили свой код (вы должны были обеспечить его как редактировать к первоначальному вопросу, а не в качестве ответа).

Я думаю, ваш DOMWriter - это класс DOM4J этого имени, который, как и многие из DOM4J, довольно плохо документирован. Но я думаю, что это копирование дерева DOM4J в дерево DOM, которое вы определенно не хотите делать. Если вы действительно хотите скопировать дерево, чтобы сделать его удобным для саксонского, вы должны скопировать его в саксонское дерево, но для этого варианта использования лучше оставить его в форме DOM4J.Используйте

DocumentBuilder builder = processor.newDocumentBuilder(); 
XdmNode inDoc = builder.wrap(dom4jdoc); 

При выполнении запроса, полученный XdmValue теперь будет последовательность объектов XdmNode, каждый из которых представляет собой оболочку вокруг узла DOM4J Element. Эти узлы элементов все еще привязаны к исходному дереву DOM4J, и у них все еще есть свои исходные пространства имен. Нет необходимости сериализовать результат в лексическом XML.

Вы можете скопировать результат в значение списка, написав

List<Element> sortedNodes = new ArrayList<Element>(); 
for (XdmItem item : result) { 
    sortedNodes.add(((Element)((XdmNode)item).getExternalNode())); 
} 

, а затем (если я читаю документацию DOM4J правильно), вы можете заменить содержимое контейнера books элемента с

Element books = (Element)sortedNodes.get(0).getParent(); 
List booksContent = books.elements(); 
booksContent.clear(); 
booksContent.addAll(sortedBooks); 
+0

Спасибо, Майкл, просто FYI - я предоставил свой код в качестве ответа на этот пост. У меня все еще есть проблемы с обновлением существующего документа. Помощь приветствуется. –

+0

Благодарим вас за отзыв. Поскольку я использую Saxon HE 9.7.x, я получаю исключение в builder.wrap (документ dom4j). Я попытался зарегистрировать registerExternalObjectModel с конфигурацией, но напрасно, поскольку он не поддерживается в HE. Наша компания хочет, чтобы мы остались с изданием HE. Я действительно надеюсь, что есть альтернативный способ выполнить мое требование к xquery. –

+0

Мы с успехом применили версию HE 9.5.x для нашего требования с использованием подхода dynamicContext/documentwrapper - он не работает в версии HE 9.7.x. –

0

Спасибо, Майкл!

Я изменил свой код. новый код выглядит следующим образом. Я не мог понять, как обновить существующий документ с отсортированными записями. Помощь приветствуется. Модифицированный код ниже:

`   String expression = String.format(EXPRESSION, elementsToSort, sortExpression);//for $p in //books/book order by $p /serialNo descending return $p 

     org.w3c.dom.Document doc = new DOMWriter().write(dom4jDoc); 

     Processor processor = new Processor(false); 
     XQueryCompiler compiler = processor.newXQueryCompiler(); 
     XQueryExecutable exp = compiler.compile(expression); 
     //DocumentBuilder builder = processor.newDocumentBuilder(); 
     //XdmNode inDoc = builder.wrap(doc); 

     XQueryEvaluator evaluator = exp.load(); 
     evaluator.setSource(new DOMSource(doc)); 
     //evaluator.setContextItem(inDoc); 
     XdmValue result = evaluator.evaluate(); 

     for (XdmSequenceIterator iter = result.iterator(); iter.hasNext();) { 
      XdmItem item = iter.next(); 
      System.out.println(" sorted record: " + item.getStringValue()); 

      //TODO: How to update the original document with these sorted records? 

     } 

     //This shows the sorted records as XML BUT has the uneccessary namesspace xmlns:data="dataOfBooks" for each record. 
     StringWriter sw = new StringWriter(); 
     Serializer out = processor.newSerializer(sw); 
     out.setOutputProperty(Serializer.Property.METHOD, "xml"); 
     out.setOutputProperty(Serializer.Property.ESCAPE_URI_ATTRIBUTES, "true"); 
     out.setOutputWriter(sw); 
     processor.writeXdmValue(result, out); 
     System.out.println("sorted records XML with uneccessary namesspace issue: " + sw.toString());` 

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

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