棘手的XSLT转型

时间:2011-10-15 17:17:38

标签: xslt

假设一个标签和项目对的XML树,每个树都包含需要转换的标记:

<list>
   <label>ABC<ptr target="#note-1"/></label>
   <item><ref type="link">123</ref></item>
   <label>DEF<ptr target="#note-2"/></label>
   <item><ref type="link">456</ref></item>
   ...
</list>

(注意,<label><item>元素内的标记仅仅是一个例子。这些元素可能包含任意数量的标记。所以,嵌套标记 - up将由模板规则处理。使用XSL字符串函数等来处理这种嵌套标记并不是一个理想的解决方案,因为可能的标签数量很大。)

假设目标是将其转换为HTML无序列表,如下所示:

<ul>
   <li>ABC<sup>1</sup> <a href="link1.html">123</a></li>
   <li>DEF<sup>2</sup> <a href="link2.html">456</a></li>
   ...
</ul>

我一直在尝试将<label><item>节点对与前面的:: sibling轴匹配,例如

   <xsl:template match="list[@type='index']/item[preceding-sibling::label]" >
    <li><xsl:value-of select="./preceding-sibling::label[1]"/> <xsl:apply-templates/></li>
   </xsl:template>

但我的输出会发出<label&gt;的内容两次:一次在<li>元素之前(正确转换),再次在<li>元素内(没有转换),如下所示:

  <ul>
     ABC<sup>1</sup>
     <li>ABC <a href="link1.html">123</a></li>
     DEF<sup>2</sup>
     <li>DEF <a href="link2.html">456</a></li>
     ...
  </ul>

我了解<label>内的<li>内容未被转换,因为我正在使用<xsl:value-of>。我只是想说明我想要在<label>内获取<item> <li>的内容所实现的目标。

如果我添加以下模板以禁止<label>元素中的第二个内容实例:

<xsl:template match="list[@type='index']/label"></xsl:template>

然后消除<label>的冗余内容集,但不是正确的内容。如,

<ul>
     <li>ABC <a href="link1.html">123</a></li>
     <li>DEF <a href="link2.html">456</a></li>
     ...
  </ul>

所以,我的问题是,如何将<label><item>中的内容转换为单个<li>元素,同时让其他模板处理该内容我的样式表?

1 个答案:

答案 0 :(得分:1)

这在XSLT中非常简单

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="list">
  <ul>
    <xsl:apply-templates select="label"/>
  </ul>
 </xsl:template>
 <xsl:template match="label">
  <li>
   <xsl:value-of select="."/>

   <xsl:variable name="vPos" select=
       "substring-after(ptr/@target, '#note-')"/>
   <sup>
     <xsl:value-of select="$vPos"/>
   </sup>
   <xsl:apply-templates select=
      "following-sibling::*[1][self::item]">
    <xsl:with-param name="pPos" select="$vPos"/>
   </xsl:apply-templates>
  </li>
 </xsl:template>

 <xsl:template match="item">
  <xsl:param name="pPos"/>
   <a href="{@type}{$pPos}.html">
     <xsl:value-of select="."/>
   </a>
 </xsl:template>
</xsl:stylesheet>

对提供的XML文档应用此转换(已更正为正确):

<list>
   <label>ABC<ptr target="#note-1"/></label>
   <item><ref type="link">123</ref></item>
   <label>DEF<ptr target="#note-2"/></label>
   <item><ref type="link">456</ref></item>
</list>

产生了想要的正确结果

<ul>
   <li>ABC<sup>1</sup>
      <a href="1.html">123</a>
   </li>
   <li>DEF<sup>2</sup>
      <a href="2.html">456</a>
   </li>
</ul>