XSL уникальные значения на узел на позицию - PullRequest
1 голос
/ 30 апреля 2010

это становится еще сложнее:)

теперь в последнем вопросе я столкнулся с другой проблемой: нам удалось получить уникальные значения только из одного родительского узла

теперь с:

<?xml version="1.0" encoding="ISO-8859-1"?>
<roots>
     <root>
          <name>first</name>
          <item>
               <something>A</something>
               <something>A</something>
          </item>
          <item>
               <something>B</something>
               <something>A</something>
          </item>
          <item>
               <something>C</something>
               <something>P</something>
          </item>
          <item>
               <something>A</something>
               <something>L</something>
          </item>
          <item>
               <something>A</something>
               <something>A</something>
          </item>
          <item>
               <something>B</something>
               <something>A</something>
          </item>
          <item>
               <something>D</something>
               <something>A</something>
          </item>
     </root>
     <root>
          <name>second</name>
          <item>
               <something>E</something>
               <something>A</something>
          </item>
          <item>
               <something>B</something>
               <something>A</something>
          </item>
          <item>
               <something>F</something>
               <something>A</something>
          </item>
          <item>
               <something>A</something>
               <something>A</something>
          </item>
          <item>
               <something>A</something>
               <something>A</something>
          </item>
          <item>
               <something>B</something>
               <something>H</something>
          </item>
          <item>
               <something>D</something>
               <something>G</something>
          </item>
     </root>
</roots>

теперь мне нужно получить уникальные значения, зависящие только от одного узла ранее, но только от элементов на второй позиции

  <?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes" method="text"/>
  <xsl:key name="item-by-value" match="something"
 use="concat(normalize-space(.), ' ', generate-id(./ancestor::root))"/>
<xsl:key name="rootkey" match="root" use="name"/>
  <xsl:template match="/">
 <xsl:for-each select="key('rootkey','first')">
<xsl:for-each select="item/something[1]">
<xsl:sort />
  <xsl:if test="generate-id() = generate-id(key('item-by-value', 
                  concat(normalize-space(.), ' ', generate-id(./ancestor::root))))">
  <xsl:value-of select="."/>
 </xsl:if>
</xsl:for-each> 
<xsl:text>_________</xsl:text>
<xsl:for-each select="item/something[2]">
<xsl:sort />
  <xsl:if test="generate-id() = generate-id(key('item-by-value', 
                  concat(normalize-space(.), ' ', generate-id(./ancestor::root))))">
  <xsl:value-of select="."/>
 </xsl:if>
</xsl:for-each> 
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

с этим XSL я получаю ABCD_________LP где мне нужен результат ABCD _________ ALP

есть идеи?

Ответы [ 3 ]

1 голос
/ 30 апреля 2010

Еще раз, проблема в том, что если вы хотите сказать «первый узел с этим содержимым под этим корнем появляется в этой позиции в item узле », то вы должны добавить «позицию в узле item к ключу. Вы можете сделать это, используя два отдельных ключа, как это делает решение Dimitre, или изменить свой ключ на:

use="concat(normalize-space(.), ' ', 
     count(./preceding-sibling::something), ' ', generate-id(./ancestor::root))"/>

А затем сделайте ваши два тестовых выражения похожими на:

<xsl:if test="generate-id() = generate-id(key('item-by-value', 
              concat(normalize-space(.), ' 0 ', generate-id(./ancestor::root))))">

и

<xsl:if test="generate-id() = generate-id(key('item-by-value', 
              concat(normalize-space(.), ' 1 ', generate-id(./ancestor::root))))">
1 голос
/ 30 апреля 2010

Просто небольшое изменение моего ответа на ваш предыдущий вопрос, и вы его получили!

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:key name="kSomethingByNameAndVal-1" match="something[1]"
  use="concat(../../name, '+', .)"/>

 <xsl:key name="kSomethingByNameAndVal-2" match="something[2]"
  use="concat(../../name, '+', .)"/>

 <xsl:template match="/">
   <xsl:for-each select="*/*">
     <xsl:for-each select=
      "item/something[1]
             [generate-id()
             =
              generate-id(key('kSomethingByNameAndVal-1',
                               concat(../../name, '+', .)
                              )
                          )
             ]
      ">

       <xsl:value-of select="."/>
     </xsl:for-each>
     <xsl:text>&#xA;</xsl:text>

     <xsl:for-each select=
      "item/something[2]
             [generate-id()
             =
              generate-id(key('kSomethingByNameAndVal-2',
                               concat(../../name, '+', .)
                              )
                          )
             ]
      ">

       <xsl:value-of select="."/>
     </xsl:for-each>
     <xsl:text>&#xA;</xsl:text>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML, будут получены требуемые, правильные результаты :

ABCD
APL
EBFAD
AHG
0 голосов
/ 30 апреля 2010

Я знаю, что вы ограничены XSLT 1.0 и используете Xalan, но я собираюсь добавить этот ответ на тот случай, если он может помочь кому-то еще в будущем выполнить поиск. (Это может использовать XSLT 2.0.) Надеюсь, вы не против.

Также я использую Saxon-HE 9.2.0.6 для процессора.

Вот таблица стилей:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="text"/>

   <xsl:template match="/roots">
      <xsl:for-each select="root">
         <xsl:value-of select="distinct-values(item/something[1])"/>___<xsl:value-of select="distinct-values(item/something[2])"/>
         <xsl:text>&#xA;</xsl:text>
      </xsl:for-each>
   </xsl:template>

</xsl:stylesheet>

Вот вывод с использованием вашего XML:

A B C D___A P L
E B F A D___A H G

Если вы хотите удалить пробелы из выходных данных, вы можете поместить выходные данные в переменную, а затем использовать replace для удаления пробелов. (Кто-нибудь знает лучший способ?)

стилевой:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="text"/>

   <xsl:template match="/roots">
      <xsl:variable name="output">
         <xsl:for-each select="root">
            <xsl:value-of select="distinct-values(item/something[1])"/>___<xsl:value-of select="distinct-values(item/something[2])"/>
            <xsl:text>&#xA;</xsl:text>
         </xsl:for-each>
      </xsl:variable>
      <xsl:value-of select="replace($output,' ','')"/>
   </xsl:template>

</xsl:stylesheet>

Выход:

ABCD___APL
EBFAD___AHG
...