当源包含平面标记时,转换为在一个列表中嵌套项目

时间:2013-03-01 16:38:39

标签: xslt xslt-2.0

我有以下XML文件:

<li id="s9781452281988.n39.i34"><i>See also</i>
<a class="term-ref" id="s9781452281988.n39.i6525" href="#s9781452281988.n39.i1899">Emotion</a>;
    <a class="term-ref" id="s9781452281988.n39.i6526" href="#s9781452281988.n39.i3312">Interpersonal conflict</a></li>

我希望输出如下:

<item>See also
 <list rend="runon">
     <item><term>Emotion</term></item>
     <item><term>Interpersonal conflict</term></item>
 </list>
</item>

基本上如果我有多个[@ class ='term-ref'],第一个实例应该开始 list rend =“runon”,然后是[@ class ='term-ref ']应作为项目/术语包含在列表中。

以下是我的尝试,但它没有按照我的希望工作,并且在第二个项目/术语之前关闭列表(元素也不是正在输出):

<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0">

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

<xsl:template match="a[@class='term-ref'][1]">
    <xsl:element name="list">
        <xsl:attribute name="rend" select="'runon'"/>
        <xsl:element name="item">
            <xsl:element name="term">
                <xsl:apply-templates/>
            </xsl:element>
        </xsl:element>
        <xsl:if test="a[@class='term-ref'][position() >1]">
            <xsl:element name="item">
                <xsl:element name="term">
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:element>
        </xsl:if>
    </xsl:element>
</xsl:template>

<xsl:template match="li//text()">
    <xsl:value-of select="translate(., '.,;', '')"/>
</xsl:template>

</xsl:stylesheet>

在源XML上,上面的样式表产生了这个输出:

<item>See also
<list rend="runon">
    <item><term>Emotion</term></item>
</list>
    Interpersonal conflict</item>

哪个不对。

我做错了什么?

3 个答案:

答案 0 :(得分:1)

这个简短的转换(几乎完全是“推送式”,没有条件说明,没有xsl:element,没有不必要的函数调用,如translate()replace()):

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

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

 <xsl:template match="a[@class='term-ref'][1]">
     <list rend="runon">
         <xsl:apply-templates mode="group"
              select="../a[@class='term-ref']"/>
     </list>
 </xsl:template>

 <xsl:template match="a[@class='term-ref']" mode="group">
    <item><term><xsl:apply-templates/></term></item>
 </xsl:template>
 <xsl:template match="a[@class='term-ref']|li/text()" priority="-1"/>
</xsl:stylesheet>

应用于提供的XML文档时 - 格式良好:

<li id="s9781452281988.n39.i34"><i>See also</i>
  <a class="term-ref" id="s9781452281988.n39.i6525"
     href="#s9781452281988.n39.i1899">Emotion</a>;
  <a class="term-ref" id="s9781452281988.n39.i6526"
     href="#s9781452281988.n39.i3312">Interpersonal conflict.</a>.
</li>

会产生想要的正确结果:

<item>See also<list rend="runon">
      <item>
         <term>Emotion</term>
      </item>
      <item>
         <term>Interpersonal conflict.</term>
      </item>
   </list>
</item>

答案 1 :(得分:0)

这应该有用......

XML输入(格式正确)

<doc>
    <li id="s9781452281988.n39.i34"><i>See also</i>
        <a class="term-ref" id="s9781452281988.n39.i6525" href="#s9781452281988.n39.i1899">Emotion</a>;
        <a class="term-ref" id="s9781452281988.n39.i6526" href="#s9781452281988.n39.i3312">Interpersonal conflict.</a>.
    </li>
</doc>

XSLT 2.0

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

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="li">
        <item>
            <xsl:apply-templates select="i/text()"/>
            <xsl:if test="a">
                <list rend="runon">
                    <xsl:apply-templates select="a"/>                   
                </list>
            </xsl:if>
        </item>
    </xsl:template>

    <xsl:template match="a">
        <item><term><xsl:apply-templates select="node()"/></term></item>
    </xsl:template>

    <xsl:template match="li//text()">
        <xsl:value-of select="replace(.,'[.,;]','')"/>
    </xsl:template>

</xsl:stylesheet>

<强>输出

<doc>
   <item>See also<list rend="runon">
         <item>
            <term>Emotion</term>
         </item>
         <item>
            <term>Interpersonal conflict</term>
         </item>
      </list>
   </item>
</doc>

答案 2 :(得分:0)

这应该做你想做的事情:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
 exclude-result-prefixes="xs"
version="2.0">

  <xsl:template match="li">
    <xsl:element name="item">
      <xsl:apply-templates select="node()" />
      <xsl:apply-templates select="." mode="items" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="li//text()">
    <xsl:value-of select="normalize-space(translate(., '.,;', ''))"/>
  </xsl:template>
  <xsl:template match="a[@class = 'term-ref']" />

  <xsl:template match="node()" mode="items" />
  <xsl:template match="li" mode="items">
    <xsl:apply-templates mode="items" />
  </xsl:template>
  <xsl:template match="li[count(a[@class = 'term-ref']) > 1]" mode="items">
    <list rend="runon">
      <xsl:apply-templates select="a[@class = 'term-ref']" mode="items" />
    </list>
  </xsl:template>

  <xsl:template match="a[@class = 'term-ref']" mode="items">
    <item>
      <term>
        <xsl:value-of select="."/>
      </term>
    </item>
  </xsl:template>
</xsl:stylesheet>

在样本输入上运行时,会产生:

<item>
  See also<list rend="runon">
    <item>
      <term>Emotion</term>
    </item>
    <item>
      <term>Interpersonal conflict</term>
    </item>
  </list>
</item>

在只有一个a.term-ref的输入文件上运行时,会产生:

<item>
  See also<item>
    <term>Interpersonal conflict</term>
  </item>
</item>