2012-06-28 43 views
1

这是我的XML文档。在xslt 2.0中有递归函数吗?

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"> 
    <w:body> 
     <w:p> 
      <w:pPr> 
      </w:pPr> 
      <w:r> 
       <w:t>Text1-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
       <w:pStyle w:val="Heading2" /> 
      </w:pPr> 
      <w:r> 
       <w:t>Text2-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
      </w:pPr> 
      <w:r> 
       <w:t>Text3-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
      </w:pPr> 
      <w:r> 
       <w:t>Text4-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
       <w:pStyle w:val="Heading3" /> 
      </w:pPr> 
      <w:r> 
       <w:t>Text2.1-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
       <w:pStyle w:val="Heading2" /> 
      </w:pPr> 
      <w:r> 
       <w:t>Text5-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
      </w:pPr> 
      <w:r> 
       <w:t>Text6-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
       <w:pStyle w:val="Heading3" /> 
      </w:pPr> 
      <w:r> 
       <w:t>Text7-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
      </w:pPr> 
      <w:r> 
       <w:t>Text8-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
       <w:pStyle w:val="Heading1" /> 
      </w:pPr> 
      <w:r> 
       <w:t>Text9-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
      </w:pPr> 
      <w:r> 
       <w:t>Text10-</w:t> 
      </w:r> 
     </w:p> 

<w:p> 
      <w:pPr> 
       <w:pStyle w:val="Heading2" /> 
      </w:pPr> 
      <w:r> 
       <w:t>Text11-</w:t> 
      </w:r> 
     </w:p> 

     <w:p> 
      <w:pPr> 
      </w:pPr> 
      <w:r> 
       <w:t>Text12-</w:t> 
      </w:r> 
     </w:p> 


    </w:body> 
    </w:document> 

一位成员#1张贴XSLT解决方案this.But它不会对上述工作的提到的XML文档。

XSLT文件:

<xsl:stylesheet 
    version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xpath-default-namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:mf="http://example.com/mf" 
    exclude-result-prefixes="xs w mf"> 

<xsl:output indent="yes"/> 

<xsl:function name="mf:group" as="element()*"> 
    <xsl:param name="paragraphs" as="element()*"/> 
    <xsl:param name="level" as="xs:integer"/> 
    <xsl:for-each-group select="$paragraphs" group-starting-with="p[pPr/pStyle/@w:val = concat('Heading', $level)]"> 
    <xsl:choose> 
     <xsl:when test="self::p[pPr/pStyle/@w:val = concat('Heading', $level)]"> 
     <xsl:element name="Heading{$level}"> 
      <Title><xsl:value-of select="r/t"/></Title> 
      <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/> 
     </xsl:element> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:apply-templates select="current-group()"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:for-each-group> 
</xsl:function> 

<xsl:template match="document"> 
    <Document> 
    <xsl:sequence select="mf:group(body/p, 1)"/> 
    </Document> 
</xsl:template> 

<xsl:template match="p"> 
    <Paragraph> 
    <xsl:value-of select="r/t"/> 
    </Paragraph> 
</xsl:template> 

</xsl:stylesheet> 

我所需的输出是:

<document> 
    <paragraph>Text1-</paragraph> 
    <Heading2> 
     <Title>Text2-</Title> 
     <paragraph>Text3-</paragraph> 
     <paragraph>Text4-</paragraph> 
    <Heading3> 
     <Title>Text2.1-</Title> 
     </Heading3> 
    </Heading2> 
     <Heading2> 
     <Title>Text5-</Title> 
     <paragraph>Text6-</paragraph> 
     <Heading3> 
      <Title>Text7-</Title> 
      <paragraph>Text8-</paragraph> 
     </Heading3> 
     </Heading2> 
    <Heading1> 
     <Title>Text9-</Title> 
     <paragraph>Text10-</paragraph> 
     <Heading2> 
     <Title>Text11-</Title> 
     <paragraph>Text12-</paragraph> 
    </Heading2> 
    </Heading1> 
</document> 

生成的输出是:

<Document> 
    <Paragraph>Text1-</Paragraph> 
    <Paragraph>Text2-</Paragraph> 
    <Paragraph>Text3-</Paragraph> 
    <Paragraph>Text4-</Paragraph> 
    <Paragraph>Text2.1-</Paragraph> 
    <Paragraph>Text5-</Paragraph> 
    <Paragraph>Text6-</Paragraph> 
    <Paragraph>Text7-</Paragraph> 
    <Paragraph>Text8-</Paragraph> 
    <Heading1> 
     <Title>Text9-</Title> 
     <Paragraph>Text10-</Paragraph> 
     <Heading2> 
     <Title>Text11-</Title> 
     <Paragraph>Text12-</Paragraph> 
     </Heading2> 
    </Heading1> 
</Document> 

钙ñ你帮我解决这个情况...

回答

1

这是一个适应的代码,应该给你想要的输出样本你发布在这个问题,它调用函数进行递归的分组,只要有与元素w:pPr/w:pStyle/@w:val="HeadingX"

<xsl:stylesheet 
    version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xpath-default-namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:mf="http://example.com/mf" 
    exclude-result-prefixes="xs w mf"> 

<xsl:output indent="yes"/> 

<xsl:function name="mf:group" as="element()*"> 
    <xsl:param name="paragraphs" as="element()*"/> 
    <xsl:param name="level" as="xs:integer"/> 
    <xsl:for-each-group select="$paragraphs" group-starting-with="p[pPr/pStyle/@w:val = concat('Heading', $level)]"> 
    <xsl:choose> 
     <xsl:when test="self::p[pPr/pStyle/@w:val = concat('Heading', $level)]"> 
     <xsl:element name="Heading{$level}"> 
      <Title><xsl:value-of select="r/t"/></Title> 
      <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/> 
     </xsl:element> 
     </xsl:when> 
     <xsl:when test="current-group()[self::p[pPr/pStyle/@w:val = concat('Heading', $level + 1)]]"> 
     <xsl:sequence select="mf:group(current-group(), $level + 1)"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:apply-templates select="current-group()"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:for-each-group> 
</xsl:function> 

<xsl:template match="document"> 
    <Document> 
    <xsl:sequence select="mf:group(body/p, 1)"/> 
    </Document> 
</xsl:template> 

<xsl:template match="p"> 
    <Paragraph> 
    <xsl:value-of select="r/t"/> 
    </Paragraph> 
</xsl:template> 

</xsl:stylesheet> 
+0

非常感谢您的精彩支持。它工作的很好...... – Saravanan

0

这是另一种样式表,在撒克逊测试。它稍微冗长一点,但效率更高,因为与Martin的解决方案不同,它将递归限制在必要的最小值。

<xsl:stylesheet 
    version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:fn="http://www.w3.org/2005/xpath-functions" 
    xmlns:user="http://stackoverflow.com/questions/11239392" 
    exclude-result-prefixes="xsl xs fn w user"> 

<xsl:output indent="yes"/> 

<xsl:function name="user:level-of-p" as="xs:string"> 
<xsl:param name="para" as="element()" /> 
<xsl:sequence select="substring($para/w:pPr/w:pStyle/@w:val, 8)" /> 
</xsl:function> 

<xsl:template name="grouped-p"> 
<xsl:param name="p-nodes" as="element()*" /> 

<xsl:variable name="vals" as="xs:integer*"> 
    <xsl:for-each select="$p-nodes[user:level-of-p(.)]"> 
    <xsl:sort data-type="number" order="ascending" select="user:level-of-p(.)" /> 
    <xsl:sequence select="user:level-of-p(.) cast as xs:integer" /> 
    </xsl:for-each> 
</xsl:variable> 
<xsl:variable name="level" as="xs:integer" select="($vals,-1)[1]" /> 
<xsl:choose> 
    <xsl:when test="$level = -1"> 
    <xsl:apply-templates select="$p-nodes" /> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:variable name="grouping-val" select="concat('Heading',$level)" /> 
    <xsl:for-each-group select="$p-nodes" group-starting-with="w:p[w:pPr/w:pStyle/@w:val = $grouping-val]"> 
    <xsl:choose> 
     <xsl:when test="user:level-of-p(.)"> 
     <xsl:element name="{$grouping-val}"> 
     <Title><xsl:value-of select="w:r/w:t[1]" /></Title> 
     <xsl:call-template name="grouped-p"> 
     <xsl:with-param name="p-nodes" select="current-group()[position() > 1]" /> 
     </xsl:call-template> 
     </xsl:element> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:call-template name="grouped-p"> 
     <xsl:with-param name="p-nodes" select="current-group()" /> 
     </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:for-each-group> 
    </xsl:otherwise> 
</xsl:choose> 
</xsl:template> 

<xsl:template match="w:document"> 
    <document> 
    <xsl:call-template name="grouped-p"> 
    <xsl:with-param name="p-nodes" select="w:body/w:p" /> 
    </xsl:call-template> 
    </document> 
</xsl:template> 

<xsl:template match="w:p"> 
    <paragraph> 
    <xsl:value-of select="w:r/w:t"/> 
    </paragraph> 
</xsl:template> 

</xsl:stylesheet>