使用 XSLT muenchian-grouping 进行嵌套分组

Nested grouping using XSLT muenchian-grouping

我必须使用 Oracle Service Bus 在 xslt 1.0 中对 xml 文档进行分组。

这是示例输入文件(简体):

    <?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>

预期o/p

<?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没有分组。告诉我哪里错了!!

o/p 对于我的 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>

提前致谢!

此解决方案不是基于 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 个子元素的元素,或者简单地说,"parents of the property elements to be grouped by @name"。 您也可以将模板匹配更改为:

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

for-each 在第一个 property 上,在当前父项中具有特定的 @name 值(请参阅使用 preceding-sibling 的条件)。 对于每次迭代,模板应用于 property 元素的所有子元素,当前(对于每个元素的)@name,即,将单个父元素的 property 元素分组@name的价值。

内部 property 元素调用相同的模板,甚至按 @name.

分组

下面是使用 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: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>