2015-02-10 111 views
2

我不得不组使用Oracle服务总线在XSLT 1.0的XML文档。嵌套分组使用XSLT muenchian-分组

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

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

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> 

在此先感谢!

+0

除了可以发布您的预期输出,你可以在你想做些什么的话解释一下吗?了解样式表需要一段时间。 – 2015-02-10 09:17:04

+0

我只是想组一个元素本身下的特定元素内的所有单独的行。如在,不重复元素C.只需按行分开它们。这必须进一步完成到一个元素内部。这是哪里出了问题occurst – HeisenBerg 2015-02-10 09:19:02

+0

没有足够的解释。你能不能详细说明一下。另外,我没有看到你的输入和预期的输出是同步的,例如,我可以看到'Status133'在你的预期输出文本节点,而不是输入。你能解决这个问题吗? – 2015-02-10 09:23:37

回答

2

而且这里去使用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> 
1

该解决方案不是基于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元素的父代将被@name分组”。 您可能,以及,模板匹配更改为:

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

for-each是第一property在当前父特定@name值(参见使用preceding-sibling的条件)。 而对于每一次迭代,模板被施加为与当前(for-each元素的)@name,即,可以通过@name的值分组单亲的property元件property元素的所有子元素。

相同的模板被称为用于内property元件,分组甚至那些由@name

+0

好工作Lingamurthy。谢谢。它工作正常。你能简单解释一下吗? – HeisenBerg 2015-02-10 11:30:16

+0

虽然我无法想出使用Muenchian的分组方法,但我很高兴它帮助你。让我用一些解释来编辑我的答案。 – 2015-02-10 11:31:54

+0

@HeisenBerg请使用Muenchian的分组查看我的第二个答案。 – 2015-02-10 12:17:55