XSLT группировка по записям атрибутов из списка - PullRequest
0 голосов
/ 20 июня 2011

У меня проблема с получением правильного XSLT для создания группы элементов на основе значения атрибута.Это мой XML:

<companies>
  <country iso="DE">
    <item name="Strawberry Raw Pressed Juice" company="Snack Inc." />
    <item name="Apple Raw Pressed Juice" company="Max Food Ltd." />
    <item name="Sweet Apple Raw Pressed Juice" company="Snack Inc." />
  </country>
  <country iso="SE">
    <item name="Sweet Mixed Pickles" company="Snack Inc." />
    <item name="Apple Raw Pressed Juice" company="Baked Beans A/S" />
    <item name="Leisure Luv Apples" company="Snack Inc." />
  </country>
</companies>

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

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

Если я теперь для каждого для элементов, я получаю все элементы.Но я хотел бы сначала получить список уникальных названий компаний, поэтому сгруппируйте элементы внутри них.

Должен ли я сделать два преобразования, может быть?Сначала сгруппировать элементы в дублирующие узлы компании, а затем во втором преобразовании поместить их в одно поле?

Ответы [ 4 ]

3 голосов
/ 20 июня 2011

Это преобразование :

<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="kItemByCompCountry" match="item"
  use="concat(../@iso,'+++',@company)"/>

 <xsl:template match="*[not(self::item)]">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match=
  "item[generate-id()
       =
        generate-id(key('kItemByCompCountry',
                        concat(../@iso,
                              '+++',@company)
                        )[1]
                    )
       ]
  ">
  <company name="{@company}">
   <xsl:copy-of select=
   "key('kItemByCompCountry',
        concat(../@iso,'+++',@company))"/>
  </company>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<companies>
    <country iso="DE">
        <item name="Strawberry Raw Pressed Juice" company="Snack Inc." />
        <item name="Apple Raw Pressed Juice" company="Max Food Ltd." />
        <item name="Sweet Apple Raw Pressed Juice" company="Snack Inc." />
    </country>
    <country iso="SE">
        <item name="Sweet Mixed Pickles" company="Snack Inc." />
        <item name="Apple Raw Pressed Juice" company="Baked Beans A/S" />
        <item name="Leisure Luv Apples" company="Snack Inc." />
    </country>
</companies>

дает желаемый, правильный результат :

<companies>
  <country iso="DE">
    <company name="Snack Inc.">
      <item name="Strawberry Raw Pressed Juice" company="Snack Inc." />
      <item name="Sweet Apple Raw Pressed Juice" company="Snack Inc." />
    </company>
    <company name="Max Food Ltd.">
      <item name="Apple Raw Pressed Juice" company="Max Food Ltd." />
    </company>
  </country>
  <country iso="SE">
    <company name="Snack Inc.">
      <item name="Sweet Mixed Pickles" company="Snack Inc." />
      <item name="Leisure Luv Apples" company="Snack Inc." />
    </company>
    <company name="Baked Beans A/S">
      <item name="Apple Raw Pressed Juice" company="Baked Beans A/S" />
    </company>
  </country>
</companies>
1 голос
/ 20 июня 2011
<xsl:key name="groupCompanies" match="item" use="@company" />

<xsl:template match="companies">

  <xsl:for-each select="//item[generate-id() = generate-id( key('groupCompanies', @company)) [1] ) ]">
    <xsl:sort select="@company" order="ascending" />
    <xsl:call-template name="group">
        <xsl:with-param name="ck" select="@company" />
      </xsl:call-template>
  </xsl:for-each>

</xsl:template>

<xsl:template name="group">
  <xsl:param name="ck" /> 

  <xsl:for-each select="//item[@company = $ck]">
     ....
  </xsl:for-each>

</xsl:template>
</xsl:stylesheet>
1 голос
/ 20 июня 2011

Не «для каждого» вообще, вам это не нужно.Вы можете выполнить группировку непосредственно из элемента country:

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

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="country">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="item[
                 preceding-sibling::item/@company!=@company]" 
                 mode="group"/>
        </xsl:copy>
    </xsl:template>

        <xsl:template match="item" mode="group">
            <company name="{@company}">
                <xsl:apply-templates select="../item[
                        @company=current()/@company]"/>
            </company>
        </xsl:template>

        <xsl:template match="item">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
</xsl:stylesheet>

. Эта трансформация производит:

<companies>
   <country iso="DE">
      <company name="Max Food Ltd.">
         <item name="Apple Raw Pressed Juice" company="Max Food Ltd."/>
      </company>
      <company name="Snack Inc.">
         <item name="Strawberry Raw Pressed Juice" company="Snack Inc."/>
         <item name="Sweet Apple Raw Pressed Juice" company="Snack Inc."/>
      </company>
   </country>
   <country iso="SE">
      <company name="Baked Beans A/S">
         <item name="Apple Raw Pressed Juice" company="Baked Beans A/S"/>
      </company>
      <company name="Snack Inc.">
         <item name="Sweet Mixed Pickles" company="Snack Inc."/>
         <item name="Leisure Luv Apples" company="Snack Inc."/>
      </company>
   </country>
</companies>
1 голос
/ 20 июня 2011

Как это?:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:key name="company" match="item" use="@company" />

   <xsl:template match="companies">
     <xsl:copy>
       <xsl:for-each select="country/item[generate-id() = generate-id(key('company',@company)[1])]">
         <xsl:variable name="company" select="@company" />
         <company name="{$company}">
           <xsl:apply-templates select="../../country/item[@company = $company]" />
         </company>
       </xsl:for-each>
     </xsl:copy>
   </xsl:template>

   <xsl:template match="item">
     <item name="{@name}" country="{../@iso}" />
   </xsl:template>
</xsl:stylesheet>

При этом используется метод группировки по Мюнхену для группировки по компании. Google для этого, если вам нужно знать больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...