1

我有这个 XML 文档,我想在其中使用 XSLT 将其修改为不同的格式。我目前面临的问题是找到标签相对于根而不是父级的绝对位置。

例如下面的例子:

<book>
  <section>
     <chapter>
     </chapter>
  </section>
</book>
<book>
  <section>
     <chapter>
     </chapter>
  </section>
</book>    <book>
  <section>
     <chapter>
     </chapter>
  </section>
</book>    <book>
  <section>
     <chapter>
     </chapter>
  </section>
</book>

期望的输出:

<book id=1>
  <section id=1>
     <chapter id=1>
     </chapter>
  </section>
</book>
<book id=2>
  <section id=2>
     <chapter id=2>
     </chapter>
  </section>
</book>    
<book id=3>
  <section id=3>
     <chapter id=3>
     </chapter>
  </section>
</book>    
<book id=4>
  <section id=4>
     <chapter id=4>
     </chapter>
  </section>
</book>

使用 position() 可以很容易地获得图书标签的 id,但是一旦我们进入章节和章节,事情就会变得更加棘手。

解决这个问题的方法是创建一个全局变量,作为节和章的计数器,每次在文档中找到这些标记之一时,全局变量都会增加,但 XSLT 中的变量表现得像常量。

提前致谢,

fbr

4

3 回答 3

1

xsl:number是为这种情况而构建的。

它使得生成各种格式的数字和计数变得非常容易,并且经常在XSL-FO中用于诸如目录和图形和表格的标签(例如图 3.a,第 1.1 节等)之类的东西。

我通过添加一个文档元素来调整示例 XML 以使其格式良好。

使用此样式表会产生所需的输出。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="/">
            <xsl:apply-templates select="*/book" />
</xsl:template>

    <xsl:template match="*">
        <xsl:copy>
            <xsl:attribute name="id">   
                <xsl:number format="1 " level="single" count="book"/>
            </xsl:attribute>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
于 2010-03-06T02:12:09.333 回答
0

ID 必须是整数吗?生成唯一 ID 的一种简单方法是创建它们并将其父级附加到它们:

<book id="1">
  <section id="1.1">
     <chapter id="1.1.1">
     </chapter>
  </section>
</book>

在这种情况下,您可以使用position()递归来轻松生成 ID。

于 2010-03-05T18:02:38.907 回答
0

怎么样

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="*|@*|text()">
    <xsl:copy>
        <xsl:apply-templates select="*|@*|text()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="book|section|chapter">
    <xsl:copy>
           <xsl:attribute name="ix">
                <xsl:value-of select="1 + count(preceding::*[name() = name(current())])"/>
            </xsl:attribute> 
        <xsl:apply-templates select="*|@*|text()" />
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

(使用“ix”而不是“id”,因为您的 XML 中确实不应该有多个具有相同 id 的元素)

于 2010-03-06T01:31:07.310 回答