我有一个XML(它是ODF)的以下部分
<office:body>
<office:text text:use-soft-page-breaks="true">
<text:h text:style-name="P1" text:outline-level="1">Heading 1</text:h>
<text:p text:style-name="P2">Paragraph 1</text:p>
<text:h text:style-name="P3" text:outline-level="2">Heading 2</text:h>
<text:p text:style-name="P4">Paragraph 2</text:p>
<text:p text:style-name="P5">Paragraph 3</text:p>
<text:h text:style-name="P6" text:outline-level="3">Heading 3</text:h>
<text:p text:style-name="P7">Paragraph 4</text:p>
<text:p text:style-name="P8">Paragraph 5</text:p>
<text:p text:style-name="P9">Paragraph 6</text:p>
<text:h text:style-name="P10" text:outline-level="4">Heading 4</text:h>
<text:p text:style-name="P11">Paragraph 7</text:p>
<text:h text:style-name="P12" text:outline-level="2">Heading 2</text:h>
<text:p text:style-name="P13">Paragraph 8</text:p>
<text:p text:style-name="P14">Paragraph 9</text:p>
<text:p text:style-name="Normal">
<text:span text:style-name="T15">Paragraph 10</text:span>
</text:p>
</office:text>
</office:body>
我需要将其转换为
<Blocks>
<Block>
<Title><![CDATA[Heading 2]]></Title>
<Content>
<![CDATA[<p>Paragraph 2</p><p>Paragraph 3</p><h3>Heading 3</h3><p>Paragraph 4</p><p>Paragraph 5</p><p>Paragraph 6</p><h4>Heading 4</h4><p>Paragraph 7</p>]]>
</Content>
</Block>
<Block>
<Title><![CDATA[Heading 2]]></Title>
<Content>
<![CDATA[<p>Paragraph 8</p><p>Paragraph 9</p><p>Paragraph 10</p>]]>
</Content>
</Block>
</Blocks>
正如您所看到的,我想为每个text:h/@text:outline-level = 2
节点创建一个Block
元素。
以下所有text:p
和text:h/@text:outline-level > 2
同级应放置在刚刚创建的Block
元素内的Content
元素中。
我怎样才能做到这一点?
这里有一个部分解决方案:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:office="http://example.com/office"
xmlns:text="http://example.com/text"
exclude-result-prefixes="office text">
<xsl:output indent="yes" cdata-section-elements="Title"/>
<xsl:key
name="k1"
match="text:p"
use="generate-id(preceding-sibling::text:h[@text:outline-level = 2][1])"/>
<xsl:key
name="k1"
match="text:h[@text:outline-level > 2]"
use="generate-id(preceding-sibling::text:h[@text:outline-level = 2])"/>
<xsl:template match="office:text">
<Blocks>
<xsl:apply-templates select="text:h[@text:outline-level = 2]"/>
</Blocks>
</xsl:template>
<xsl:template match="text:h[@text:outline-level = 2]">
<Block>
<Title>
<xsl:value-of select="."/>
</Title>
<Content>
<xsl:apply-templates select="key('k1', generate-id())"/>
</Content>
</Block>
</xsl:template>
<xsl:template match="text:p">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="text:h[@text:outline-level = 3]">
<h3>
<xsl:apply-templates/>
</h3>
</xsl:template>
<xsl:template match="text:h[@text:outline-level = 4]">
<h4>
<xsl:apply-templates/>
</h4>
</xsl:template>
</xsl:stylesheet>
它转换
<office:body xmlns:office="http://example.com/office" xmlns:text="http://example.com/text">
<office:text text:use-soft-page-breaks="true">
<text:h text:style-name="P1" text:outline-level="1">Heading 1</text:h>
<text:p text:style-name="P2">Paragraph 1</text:p>
<text:h text:style-name="P3" text:outline-level="2">Heading 2</text:h>
<text:p text:style-name="P4">Paragraph 2</text:p>
<text:p text:style-name="P5">Paragraph 3</text:p>
<text:h text:style-name="P6" text:outline-level="3">Heading 3</text:h>
<text:p text:style-name="P7">Paragraph 4</text:p>
<text:p text:style-name="P8">Paragraph 5</text:p>
<text:p text:style-name="P9">Paragraph 6</text:p>
<text:h text:style-name="P10" text:outline-level="4">Heading 4</text:h>
<text:p text:style-name="P11">Paragraph 7</text:p>
<text:h text:style-name="P12" text:outline-level="2">Heading 2</text:h>
<text:p text:style-name="P13">Paragraph 8</text:p>
<text:p text:style-name="P14">Paragraph 9</text:p>
<text:p text:style-name="Normal">
<text:span text:style-name="T15">Paragraph</text:span>
</text:p>
</office:text>
</office:body>
进入
<Blocks>
<Block>
<Title><![CDATA[Heading 2]]></Title>
<Content>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
<h3>Heading 3</h3>
<p>Paragraph 4</p>
<p>Paragraph 5</p>
<p>Paragraph 6</p>
<h4>Heading 4</h4>
<p>Paragraph 7</p>
</Content>
</Block>
<Block>
<Title><![CDATA[Heading 2]]></Title>
<Content>
<p>Paragraph 8</p>
<p>Paragraph 9</p>
<p>
Paragraph
</p>
</Content>
</Block>
</Blocks>
因此,据我所知,分组已经完成,尽管第二个Block
中的最后一个p
没有出现在您所需的输出中,但由于您的口头描述"All following text:p"并不意味着我已经按照该描述进行了分组。
此外,还缺少的是将所有p
和hx
元素填充到CDATA部分中,我不确定您是否真的想要这样做,如果是这样,我建议您使用以下内容http://lenzconsulting.com/xml-to-string/或者使用扩展函数将节点序列化为文本。这可能还需要使用结果树片段和exsl:node-set或类似的方法来将结果树片段转换为用于序列化的节点集。作为替代方案,您需要更改text:p
和其他模板,以输出带有标记的文本节点,而不是元素节点。