XSLT转换xml带有子列表的列表项

时间:2019-02-13 16:38:26

标签: xslt

将感谢您的帮助。我的xml如下:

 <ul>
    <li>list item 1 </li>
    <li>List Item 2 
         <ul>
            <li>List item 2.1</li>
            <li>List Item 2.2</li>
        </ul>
    </li>
    <li>List Item 3 </li>
</ul>

输出应如下:

<list>
        <item>
            <paragraph>list item 1 </paragraph>
        </item>
        <item>
            <paragraph>List Item 2 </paragraph>
            <list>
                <item>
                    <paragraph>List<emphasis> item</emphasis> 2.1 </paragraph>
                </item>
                <item>
                    <paragraph>List Item 2.2 </paragraph>
                </item>
            </list>
        </item>
        <item>
            <paragraph>List Item 3 </paragraph>
        </item>
    </list>

我正在使用xlst 3.0版,如下所示:

<xsl:template match="ul">
    <xsl:choose>
        <xsl:when test="name(..)='li'">
            <xsl:text disable-output-escaping="yes">&lt;/paragraph&gt;</xsl:text>
            <list>
                <xsl:apply-templates/>
            </list>
        </xsl:when>
        <xsl:otherwise>
            <list>
            <xsl:apply-templates/>
        </list></xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template match="li">
    <item>
        <xsl:text disable-output-escaping="yes">&lt;paragraph&gt;</xsl:text>
        <xsl:apply-templates/>
        <xsl:text disable-output-escaping="yes">&lt;/paragraph&gt;</xsl:text>
    </item>
</xsl:template>

我几乎按照我的意愿获得了输出,但是带有额外的结束段落元素(</paragraph>)如下:

<list>
              <item><paragraph>list item 1 </paragraph></item>
              <item><paragraph>List Item 2 </paragraph><list>
                          <item><paragraph>List item 2.1 </paragraph></item>
                          <item><paragraph>List Item 2.2 </paragraph></item>
                    </list>
        </paragraph></item>
              <item><paragraph>List Item 3 </paragraph></item>
        </list>

1 个答案:

答案 0 :(得分:0)

您应避免以这种方式使用disable-output-escaping。如您所见,这确实不是一个好习惯。

对于给定的XML,您可以做的是使用一个与text()相匹配的模板,然后将paragraph包裹起来:

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

  <xsl:strip-space elements="*" />

  <xsl:template match="ul">
    <list>
      <xsl:apply-templates/>
    </list>
  </xsl:template>

  <xsl:template match="li">
    <item>
        <xsl:apply-templates/>
    </item>
  </xsl:template>

  <xsl:template match="text()">
    <paragraph>
        <xsl:value-of select="normalize-space()" />
    </paragraph>
  </xsl:template>
</xsl:stylesheet>

或者,如果您可以在文本中添加标记,例如<li>list <b>item 1</b> </li>,并且想要输出类似<paragraph>list<b>item 1</b></paragraph>的文本,则可以使用xsl:for-each-group

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

  <xsl:strip-space elements="*" />

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="ul">
    <list>
      <xsl:apply-templates/>
    </list>
  </xsl:template>

  <xsl:template match="li">
    <item>
      <xsl:for-each-group select="node()" group-ending-with="ul">
        <paragraph>
          <xsl:apply-templates select="current-group()[not(self::ul)]" />
        </paragraph>
        <xsl:apply-templates select="current-group()[self::ul]" />
      </xsl:for-each-group>
    </item>
  </xsl:template>

  <xsl:template match="text()">
    <xsl:value-of select="normalize-space()" />
  </xsl:template>
</xsl:stylesheet>