2

我有以下 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>

基本上,如果我有多个 a[@class='term-ref'],第一个实例应该启动列表rend="runon",随后的 a[@class='term-ref'] 应该作为item/term包含在名单。

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

<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>

这是不正确的。

我究竟做错了什么?

4

3 回答 3

1

这个简短的转换(几乎完全是“推式”,没有条件指令,没有xsl:element也没有不必要的函数调用,如translate()or 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>
于 2013-03-02T03:40:41.060 回答
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>
于 2013-03-01T17:28:27.293 回答
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>
于 2013-03-01T17:36:20.287 回答