2016-03-21 92 views
1

我在XSLT中苦苦挣扎了几个小时,并且来到StackOverflow寻求帮助。我有一些输入文本是这样的:使用XSLT对一些XML元素进行分组

<?xml version="1.0" encoding="UTF-8"?> 
<div> 
<p class="text">Some regular text</p> 
<p class="first">The first part</p> 
<p class="next">and then some text</p> 
<p class="next">and some more</p> 

<p class="regular">Some regular text</p> 
<p class="text1">Some regular text</p> 
<p class="text2">Some regular text</p> 
<p class="first">Here some new text</p> 
<p class="next">and some more</p> 
<p class="next">and the end of this section</p> 
<p class="text3">Some regular text</p> 
</div> 

我想这个

<?xml version="1.0" encoding="UTF-8"?> 
<div> 
<p>Some regular text</p> 

<group> 
    <p>The first part</p> 
    <p>and then some text</p> 
    <p>and some more</p> 
</group> 

<p>Some regular text</p> 
<p>Some regular text</p> 
<p>Some regular text</p> 

<group> 
    <p>Here some new text</p> 
    <p>and some more</p> 
    <p>and the end of this section</p> 
</group> 

<p>Some regular text</p> 
</div> 

我知道这是不是令人惊讶的难以结束,但我不明白这一点...的XSLT我有现在的问题是:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
exclude-result-prefixes="xs" 
version="2.0"> 
<xsl:template match="/"> 
    <xsl:apply-templates select="*" /> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:copy> 
     <xsl:for-each select="@*"> 
      <xsl:copy /> 
     </xsl:for-each> 
     <xsl:apply-templates /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="div"> 
    <lg> 
     <xsl:apply-templates/> 
    </lg> 
</xsl:template> 


<xsl:template match="/div"> 
    <xsl:for-each-group select="//p[@class='first']/following-sibling::p[@class='next']" group-by="text()"> 
     <group> 
      <xsl:apply-templates/> 
     </group> 
    </xsl:for-each-group> 
</xsl:template> 
</xsl:stylesheet> 

这并不在所有的工作:(我会很感激,如果有人可以帮助我,因为我真的有问题的理解XSLT是如何工作的?

最好的问候, 何塞

回答

2

您尝试组具有一个class属性设置为“第一”的p,其次是所有的“未来”的。

了给定的XML,XSLT这可能做的伎俩:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
<xsl:output method="xml" indent="yes" /> 

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

    <xsl:template match="/div"> 
    <xsl:for-each-group select="p" group-adjacent="@class = 'first' or @class='next'"> 
     <xsl:choose> 
      <xsl:when test="@class = 'first' or @class='next'"> 
       <group> 
        <xsl:apply-templates select="current-group()" /> 
       </group> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:apply-templates select="current-group()" /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each-group> 
</xsl:template> 

<xsl:template match="@class" /> 
</xsl:stylesheet> 

但是,这不会在这种情况下工作,因为它将把所有的p元素于一体的集团。

<div> 
<p class="first">The first part</p> 
<p class="next">and then some text</p> 
<p class="first">Here some new text</p> 
<p class="next">and some more</p> 
</div> 

如果这不是你想要的,试试这个XSLT而不是

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
<xsl:output method="xml" indent="yes" /> 

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

    <xsl:template match="/div"> 
    <xsl:for-each-group select="p" group-starting-with="p[@class='first']"> 
     <xsl:for-each-group select="current-group()" group-adjacent="@class='first' or @class='next'"> 
     <xsl:choose> 
      <xsl:when test="@class='first' or @class='next'"> 
       <group> 
        <xsl:apply-templates select="current-group()" /> 
       </group> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:apply-templates select="current-group()" /> 
      </xsl:otherwise> 
     </xsl:choose> 
     </xsl:for-each-group> 
    </xsl:for-each-group> 
</xsl:template> 

<xsl:template match="@class" /> 
</xsl:stylesheet> 
+0

添喜,感谢您的回答!据我了解,你选择这个p以负面的方式定义它们:那些没有任何阶级的p。我们能以积极的方式尝试吗?那么选择这些具有这个特定类的元素?我尝试过,如果这样会带来惊喜,它不起作用 –

+0

我编辑了xml输入以更好地覆盖它 –

+1

我已经用两个可能的XSLT更新了我的答案,您可以尝试。 –