这是我的XML文档。
<?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>
其中一个发布xslt解决方案的Stackoverflow成员。但它不适用于上面提到的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>
你能帮我解决这个问题......
答案 0 :(得分: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>
答案 1 :(得分:0)
这是另一种样式表,在Saxon上测试过。它有点冗长,但效率更高,因为与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>