Группировка при использовании 2 разных файлов XML в качестве источников?

то, что я хочу сделать, - это типичная группировка, которую обычно можно выполнить с помощью xsl: key, но она усложняется, поскольку данные для групп находятся в двух разных файлах. Как процесс? Вот пример того, что я хочу сделать, могу ли я попросить вашей помощи? должны быть совместимы с xslt-1.0.

bookreference.xml :

<t>  
    <book isbn="1">  
        <category>SF</category>  
    </book>  
    <book isbn="2">  
        <category>SF</category>  
    </book>  
    <book isbn="3">  
        <category>SF</category>  
    </book>  
    <book isbn="4">  
        <category>Comedy</category>  
    </book>  
    <book isbn="5">  
        <category>Comedy</category>  
    </book>
</t>  

mylibrary.xml:

<t>  
   <book isbn="1">
       <price>10</price>
   </book>
   <book isbn="2">
      <price>10</price>
   </book>       
   <book isbn="3">
      <price>20</price>
   </book>
   <book isbn="4">
      <price>5</price>
   </book>
</t>  

требуется вывод:

SF : 3 book(s) - Total : 40$
Comedy : 2 book(s) - Total : 5$

person Seb    schedule 30.11.2011    source источник
comment
Ну, один из возможных процессов XSLT 1.0 состоит в том, чтобы сначала объединить два документа во фрагмент результирующего дерева, а затем использовать функцию расширения, например exsl:node-set, для преобразования фрагмента результирующего дерева в набор узлов, после чего вы можете использовать мюнховскую группировку как обычно на этом наборе узлов. Итак, на какой процессор XSLT 1.0 вы ориентируетесь, есть ли у него exsl:node-set или что-то подобное?   -  person Martin Honnen    schedule 30.11.2011
comment
Привет Мартин, xsltproc как процессор XSLT 1.0. Так что все должно быть в порядке, я попробую ваш подход.   -  person Seb    schedule 30.11.2011
comment
Почему вы предоставляете искаженный XML? Есть как минимум две проблемы с каждым из двух предоставленных фрагментов. Пожалуйста, отредактируйте и исправьте.   -  person Dimitre Novatchev    schedule 30.11.2011
comment
@_Dimitre : Приношу свои извинения за некорректный XML : Исправить Готово.   -  person Seb    schedule 30.11.2011


Ответы (2)


Как уже было предложено в моем комментарии, вы можете сначала объединить два документа в фрагмент результирующего дерева, а затем использовать exsl:node-set, чтобы получить набор узлов, к которому затем можно применить мюнхианскую группировку:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  exclude-result-prefixes="exsl"
  version="1.0">

  <xsl:param name="price-url" select="'test2011113002.xml'"/>
  <xsl:variable name="doc2" select="document($price-url)"/>

  <xsl:output method="text"/>

  <xsl:variable name="rtf">
    <xsl:apply-templates select="//book" mode="merge"/>
  </xsl:variable>

  <xsl:template match="book" mode="merge">
    <xsl:copy>
      <xsl:variable name="isbn" select="@isbn"/>
      <xsl:copy-of select="@* | node()"/>
      <xsl:for-each select="$doc2">
        <xsl:copy-of select="key('k1', $isbn)/price"/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <xsl:key name="k1" match="book" use="@isbn"/>
  <xsl:key name="k2" match="book" use="category"/>

  <xsl:template match="/">
    <xsl:apply-templates select="exsl:node-set($rtf)/book[generate-id() = generate-id(key('k2', category)[1])]"/>
  </xsl:template>

  <xsl:template match="book">
    <xsl:variable name="current-group" select="key('k2', category)"/>
    <xsl:value-of select="concat($current-group/category, ': ', count($current-group), ' - Total : ', sum($current-group/price), '&#10;')"/>
  </xsl:template>

</xsl:stylesheet>
person Martin Honnen    schedule 30.11.2011
comment
@_Martin: Это можно сделать гораздо проще, без каких-либо функций расширения. - person Dimitre Novatchev; 30.11.2011

Хороший вопрос, +1.

Нет нет необходимости в сложной (более чем необходимой) группировке или каких-либо дополнительных функциях:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kBookByCat" match="book"
      use="category"/>

 <xsl:key name="kPriceByIsbn" match="price"
      use="../@isbn"/>

 <xsl:variable name="vMyLib" select=
 "document('file:///c:/temp/delete/mylibrary.xml')"/>

 <xsl:template match=
  "book[generate-id()
       =
        generate-id(key('kBookByCat', category)[1])
        ]
  ">
     <xsl:variable name="vBooksinCat" select=
          "key('kBookByCat', category)"/>

     <xsl:value-of select="category"/> : <xsl:text/>
     <xsl:value-of select="count($vBooksinCat)"/>
     <xsl:text> book(s) - Total : $</xsl:text>

     <xsl:for-each select="$vMyLib">
      <xsl:value-of select="sum(key('kPriceByIsbn', $vBooksinCat/@isbn))"/>
      <xsl:text>&#xA;</xsl:text>
     </xsl:for-each>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

Когда это преобразование применяется к первому из двух предоставленных фрагментов данных (исправлено для корректного XML-документа):

<t>
    <book isbn="1">
        <category>SF</category>
    </book>
    <book isbn="2">
        <category>SF</category>
    </book>
    <book isbn="3">
        <category>SF</category>
    </book>
    <book isbn="4">
        <category>Comedy</category>
    </book>
    <book isbn="5">
        <category>Comedy</category>
    </book>
</t>

и имея второй фрагмент данных (исправленный в правильно сформированный XML-документ), сохраненный как C:\Temp\Delete\mylibrary.xml,

Получается желаемый правильный результат:

SF : 3 book(s) - Total : $40
Comedy : 2 book(s) - Total : $5
person Dimitre Novatchev    schedule 30.11.2011
comment
@_Dimitre: спасибо за ваше решение и за то, что посоветовали мне неправильную форму xml. - person Seb; 30.11.2011
comment
@_Dimitre: после изучения вашего кода оказалось, что он не соответствует требованиям, потому что я думаю, что не смог четко объяснить свои потребности. Я хочу получить в качестве вывода количество и общую стоимость книг в моей группе «Библиотека» по семье, а не полную цену и количество книг в группе «Ссылки» по семье. Я изменяю пример, чтобы быть более явным. - person Seb; 30.11.2011
comment
@Seb: Мой ответ дает точно такие же результаты, как и в вашем вопросе, до того, как вы изменили его 10 минут назад! Если у вас есть новый вопрос -- задайте новый вопрос. На ваш вопрос ответили полностью. Кроме того, в тексте вашего вопроса нет упоминания о семье, поэтому ваш комментарий противоречит ему. Что такое семья? Пожалуйста, прекратите изменять этот вопрос, примите лучший ответ и задавайте новые вопросы. Кстати, я думаю, что решение в моем ответе по-прежнему дает правильный результат даже для измененного вопроса. - person Dimitre Novatchev; 30.11.2011
comment
@_Dimitre : семья = категория. До и после издания мой вывод был одинаковым для категории КОМЕДИЯ => Комедия: 1 книга (и) - Итого: 5 $, потому что в моей библиотеке только 1 комедийная книга. - person Seb; 30.11.2011
comment
я изменяю рассматриваемый вывод, чтобы он соответствовал результату обоих, я принимаю ответ, так как он полезен (не встречается ни на одном другом форуме), и открою новый вопрос, более тщательно объясняющий мою потребность. - person Seb; 30.11.2011
comment
@Seb: я на работе, и через 6 часов у меня будет время посмотреть ваш измененный вопрос. Что касается принятия ответа, вы уже приняли другой ответ, который излишне сложен и требует использования функции расширения, специфичной для поставщика. - person Dimitre Novatchev; 01.12.2011
comment
@_Dimitre: извините, работа stackoverflow для меня нова, мы можем принять только один ответ? У меня есть xsl, который может работать с нужным мне выводом (еще не проверен), но я уверен, что вы можете помочь его оптимизировать. Увидимся в ветке вопросов о перезаписи. - person Seb; 01.12.2011