【问题标题】:How can I group siblings in a flat XML如何在平面 XML 中对兄弟姐妹进行分组
【发布时间】:2012-07-09 14:19:56
【问题描述】:

我有一个 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:ptext:h/@text:outline-level &gt; 2 兄弟姐妹都应该放在刚刚创建的Block 元素内的Content 元素中。

我怎样才能做到这一点?

【问题讨论】:

    标签: xml xslt xslt-1.0 odf


    【解决方案1】:

    这里是部分解决方案:

    <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 没有出现在您所需的输出中,但正如您的口头描述“所有以下文本:p”没有其他建议我按照该描述进行了分组。

    此外还缺少将所有这些 phx 元素填充到 CDATA 部分中,我不确定您是否真的想要这样,如果是这样,我建议您使用类似 http://lenzconsulting.com/xml-to-string/ 或使用将节点序列化为文本的扩展函数。这可能还需要使用结果树片段并使用 exsl:node-set 或类似方法将结果树片段转换为节点集以进行序列化。作为替代方案,您需要更改 text:p 和其他模板以输出带有标记的文本节点而不是元素节点。

    【讨论】:

    • 就是这样!我的主要问题是 xsl:key,你为我完美地解决了它。最后一个p 是我的错,我只是在我的问题中澄清了它。 CDATA 中的ph3h4 是另一个问题:但经过几次尝试,它终于可以使用此模板:&lt;xsl:template match="text:p"&gt;&lt;xsl:text&gt;&amp;lt;p&amp;gt;&lt;/xsl:text&gt;&lt;xsl:apply-templates/&gt;&lt;xsl:text&gt;&amp;lt;/p&amp;gt;&lt;/xsl:text&gt;&lt;/xsl:template&gt;
    猜你喜欢
    • 2019-05-06
    • 2019-08-29
    • 1970-01-01
    • 2019-08-21
    • 2015-03-06
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多