Вложенная группировка с использованием XSLT muenchian-grouping

Мне пришлось сгруппировать документ xml в xslt 1.0 с помощью Oracle Service Bus.

Это пример входного файла (упрощенный):

    <?xml version="1.0" encoding="UTF-8"?>
    <EMailData>
       <property name="A">
          <property name="B">
               <property name="C">
                <row>
                   <property name="C1">
                      <value>ValC1</value>
                   </property>
                   <property name="C2">
                      <value>ValC2</value>
                   </property>
                   <property name="C3">
                      <value>Valc3</value>
                   </property>
                   <property name="C4">
                      <value>Valc4</value>
                   </property>
                 </row>  
             </property> 
             <property name="C">
                <row>
                   <property name="C1">
                      <value>ValC1</value>
                   </property>
                   <property name="C2">
                      <value>ValC2</value>
                   </property>
                   <property name="C3">
                      <value>Valc3</value>
                   </property>
                   <property name="C4">
                      <value>Valc4</value>
                   </property>
                 </row>  
             </property> 
             <property name="D">
                <row>
                   <property name="D1">
                      <value>ValD1</value>
                   </property>
                   <property name="D2">
                      <value>VALd2</value>
                   </property>
                   <property name="D3-InnerElement"> //Need to Group this too
                      <row>
                         <property name="Status">
                            <value>Status122</value>
                         </property>
                      </row>
                   </property>
                   <property name="D3-InnerElement">
                      <row>
                         <property name="Status">
                            <value>Status123</value>
                         </property>
                      </row>
                   </property>
                   <property name="D3-InnerElement">
                      <row>
                         <property name="Status">
                            <value>Status124</value>
                         </property>
                      </row>
                   </property>
                </row>
            </property>
             <property name="D">
                <row>
                   <property name="D1">
                      <value>ValD1</value>
                   </property>
                   <property name="D2">
                      <value>VALd2</value>
                   </property>
                   <property name="D3-InnerElement">
                      <row>
                         <property name="Status">
                            <value>Status122</value>
                         </property>
                      </row>
                   </property>
                   <property name="D3-InnerElement">
                      <row>
                         <property name="Status">
                            <value>Status123</value>
                         </property>
                      </row>
                   </property>
                   <property name="D3-InnerElement">
                      <row>
                         <property name="Status">
                            <value>Status124</value>
                         </property>
                      </row>
                   </property>
                </row>
            </property>             
          </property>
       </property>
    </EMailData>

Моя логика XSLT:

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

<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>

<xsl:key name="group" match="/*/*/*/property" use="@name"/>

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

<xsl:template match="/*/*/*[property[@name]]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each select="*[generate-id() = generate-id(key('group', @name)[1])]">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates select="key('group', @name)/*"/>
  </xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>

<!--Change for Inner Hierarchy-->

<xsl:key name="inner-group" match="/*/*/*/*/property" use="@name"/>

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

<xsl:template match="/*/*/*/*[property[@name]]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:for-each select="*[generate-id() = generate-id(key('inner-group', @name)[1])]">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates select="key('inner-group', @name)/*"/>
  </xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Ожидаемое о / п

<?xml version="1.0" encoding="UTF-8"?>
<EMailData>
   <property name="A">
      <property name="B">
         <property name="C">
            <row>
               <property name="C1">
                  <value>ValC1</value>
               </property>
               <property name="C2">
                  <value>ValC2</value>
               </property>
               <property name="C3">
                  <value>Valc3</value>
               </property>
               <property name="C4">
                  <value>Valc4</value>
               </property>
            </row>
            <row>
               <property name="C1">
                  <value>ValC1</value>
               </property>
               <property name="C2">
                  <value>ValC2</value>
               </property>
               <property name="C3">
                  <value>Valc3</value>
               </property>
               <property name="C4">
                  <value>Valc4</value>
               </property>
            </row>
         </property>
         <property name="D">
            <row>
               <property name="D1">
                  <value>ValD1</value>
               </property>
               <property name="D2">
                  <value>VALd2</value>
               </property>
               <property name="D3-InnerElement"> //Need to Group this too
                      <row>
                     <property name="Status">
                        <value>Status122</value>
                     </property>
                  </row>
               </property>
               <property name="D3-InnerElement">
                  <row>
                     <property name="Status">
                        <value>Status123</value>
                     </property>
                  </row>
                  <row>
                     <property name="Status">
                        <value>Status124</value>
                     </property>
                  </row>
               </property>
            </row>
            <row>
               <property name="D1">
                  <value>ValD1</value>
               </property>
               <property name="D2">
                  <value>VALd2</value>
               </property>
               <property name="D3-InnerElement">
                  <row>
                     <property name="Status">
                        <value>Status122</value>
                     </property>
                  </row>
                  <row>
                     <property name="Status">
                        <value>Status123</value>
                     </property>
                  </row>
                  <row>
                     <property name="Status">
                        <value>Status124</value>
                     </property>
                  </row>
               </property>
            </row>
         </property>
      </property>
   </property>
</EMailData>

Но D3-innerelement не сгруппирован. Скажи мне, где я пошел не так!!

о / п для моего XSLT

    <?xml version="1.0" encoding="UTF-8"?>
<EMailData>
   <property name="A">
      <property name="B">
         <property name="C">
            <row>
               <property name="C1">
                  <value>ValC1</value>
               </property>
               <property name="C2">
                  <value>ValC2</value>
               </property>
               <property name="C3">
                  <value>Valc3</value>
               </property>
               <property name="C4">
                  <value>Valc4</value>
               </property>
            </row>
            <row>
               <property name="C1">
                  <value>ValC1</value>
               </property>
               <property name="C2">
                  <value>ValC2</value>
               </property>
               <property name="C3">
                  <value>Valc3</value>
               </property>
               <property name="C4">
                  <value>Valc4</value>
               </property>
            </row>
         </property>
         <property name="D">
            <row>
               <property name="D1">
                  <value>ValD1</value>
               </property>
               <property name="D2">
                  <value>VALd2</value>
               </property>
               <property name="D3-InnerElement"> //Need to Group this too
                          <row>
                     <property name="Status">
                        <value>Status122</value>
                     </property>
                  </row>
               </property>
               <property name="D3-InnerElement">
                  <row>
                     <property name="Status">
                        <value>Status123</value>
                     </property>
                  </row>
               </property>
               <property name="D3-InnerElement">
                  <row>
                     <property name="Status">
                        <value>Status124</value>
                     </property>
                  </row>
               </property>
            </row>
            <row>
               <property name="D1">
                  <value>ValD1</value>
               </property>
               <property name="D2">
                  <value>VALd2</value>
               </property>
               <property name="D3-InnerElement">
                  <row>
                     <property name="Status">
                        <value>Status122</value>
                     </property>
                  </row>
               </property>
               <property name="D3-InnerElement">
                  <row>
                     <property name="Status">
                        <value>Status123</value>
                     </property>
                  </row>
               </property>
               <property name="D3-InnerElement">
                  <row>
                     <property name="Status">
                        <value>Status124</value>
                     </property>
                  </row>
               </property>
            </row>
         </property>
      </property>
   </property>
</EMailData>

Заранее спасибо!

2 ответа

Решение

И здесь идет решение с использованием группировки Мюнхена:

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

<xsl:key name="group" match="property" use="@name"/>

<xsl:template match="/EMailData/property/property | /EMailData/property/property/property/row">
    <xsl:variable name="id" select="generate-id()"/>
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:for-each select="property[count(. | key('group', @name)[$id = generate-id(parent::*)][1]) = 1]">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates select="key('group', @name)[$id = generate-id(parent::*)]/*"/>
            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Это решение не основано на группировке Muenchian, но подумал, что это будет полезно:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="*[property]">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:for-each select="property[not(@name = preceding-sibling::property/@name)]">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates select="../property[@name = current()/@name]/*"/>
            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Здесь вторым шаблоном является шаблон преобразования идентификаторов, используемый для копирования всех атрибутов и узлов.

Первый шаблон соответствует элементам хотя бы с одним property ребенок, или простыми словами, "родители property элементы для группировки @nameMsgstr "Также вы можете изменить шаблон соответствия:

<xsl:template match="/EMailData/property/property | /EMailData/property/property/property/row">

for-each на первом property с конкретным @name значение в текущем родительском элементе (см. условие, используя preceding-sibling). И для каждой итерации шаблоны применяются ко всем дочерним элементам property элементы с текущим (для каждого элемента) @nameгруппировка property элементы одного родителя по их @nameценность.

Этот же шаблон вызывается для внутреннего property элементы, сгруппированные даже по @name,

Другие вопросы по тегам