递归深度和不同的解析

时间:2014-07-02 18:43:15

标签: html xml parsing xslt

我对xslt相当新鲜。所以我试图做的是将一本书用xml解析成一个html。一个基本的例子就是这个。

<book>
    <title>
        Some important title
    </title>
    <section>
        <title>animal</title>
        <kw>RealAnimal</kw>
        <kw>something|something more about it</tkw>
        <para>Some really important facts</para>
        <section>
            <title>something</title>
            <kw>something else</kw>
            <para>Enter Text</para>
        </section>
        <section>
            <title>Even more</title>
            <kw>and more</kw>
            <para>hell of a lot more</para>
        </section>
    </section>
</book>

一个部分可以包含未知数量的子部分。显然我需要通过recusrion来处理这个问题。到目前为止,我设计了2个模板,以便根据我的需要处理书籍和部分。

<xsl:template match="book">
<html>
    <body>
        <h1><xsl:value-of select="title" /></h1>
        <xsl:apply-templates select="section" />
    </body>
</html>
</xsl:template>

<xsl:template match="section[title]">
    <li><xsl:value-of select="title" /></li>
    <!-- do something more here -->
</xsl:template>

我无法弄清楚的是,我可以获得当前的递归深度,因为我想根据深度决定使用哪种标题。

此外,本书应该由两部分组成。它在开头的正常内容,如标题下方的标题和段落。最后是一个索引。这让我相信我需要在一个文档中以两种不同的方式解析它,但我该怎么做呢?任何提示或代码将不胜感激

所以我想出了如何使用Word中的列表等数字创建节和子节标题。

<xsl:number level="multiple" />

给了我一个关于父母部分位置和自己位置的x.y基础的子部分。我现在想要的是它给了我组的数量,因为它根据深度对值进行分组,但我无法弄清楚如何

id期望它解析为

<h1>Some important title</h1>
...
<h2> animal </h2>
...
<h3> something </h3>
...
<h3> Even more </h3>

如果我要在&#34;中添加另一部分&#34; -section它将是h4,依此类推......

像这样解决了

<xsl:param name="depth"/>
<xsl:choose>
    <xsl:when test="6 > $depth">
        <xsl:element name="h{$depth}">
            <xsl:number level="multiple" />.
            <xsl:value-of select="title" />
        </xsl:element>
    </xsl:when>
    <xsl:otherwise>
        <h6><xsl:number level="multiple" />. <xsl:value-of select="title" /></h6>
    </xsl:otherwise>
</xsl:choose>

2 个答案:

答案 0 :(得分:1)

如果您真的想知道自己的深度,可以尝试修补“count(祖先:: *)”。但是,我建议先看一下自动编号,以防它成功。它甚至可以很方便地处理嵌套项目。

“XSLT的xsl:number指令可以很容易地在结果文档中插入一个数字。它的value属性允许你命名要插入的数字,但是如果你真的想在你的结果中添加一个特定的数字,那么它就简单得多了。将该数字添加为文字文本。当您从xsl:value-of指令中省略value属性时,XSLT处理器根据上下文节点在源树中的位置或xsl:中计数的节点之间的数量来计算数量。 - 每个指令,这使它非常适合自动编号。“

XML.com reference page

答案 1 :(得分:1)

  

以及我试图做的是将h2设置为部分作为子部分   书,以及h3的章节

这是你可以做到这一点的一种方式 - 无限制地嵌套子部分:

<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="/book">
    <html>
        <body>
            <h1><xsl:value-of select="title" /></h1>
            <xsl:apply-templates select="section" />
        </body>
    </html>
</xsl:template>

<xsl:template match="section">
    <h2><xsl:value-of select="title" /></h2>
    <xsl:apply-templates select="subsection">
        <xsl:with-param name="depth" select="3"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="subsection">
    <xsl:param name="depth"/>
    <xsl:element name="h{$depth}">
        <xsl:value-of select="title" />
    </xsl:element>
    <xsl:apply-templates select="subsection">
        <xsl:with-param name="depth" select="$depth + 1"/>
    </xsl:apply-templates>
</xsl:template>

</xsl:stylesheet>

请注意,此 递归无限制; AFAIK,HTML将在h6之后用完。


编辑:

  

一个小节不是名为subsection,它只是作为孩子的一个部分   另一部分。

那么这可能更简单。或者至少更短。

<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="/book">
    <html>
        <body>
            <h1><xsl:value-of select="title" /></h1>
            <xsl:apply-templates select="section">
                <xsl:with-param name="depth" select="2"/>
            </xsl:apply-templates>  
        </body>
    </html>
</xsl:template>

<xsl:template match="section">
    <xsl:param name="depth"/>
    <xsl:element name="h{$depth}">
        <xsl:value-of select="title" />
    </xsl:element>
    <xsl:apply-templates select="section">
        <xsl:with-param name="depth" select="$depth + 1"/>
    </xsl:apply-templates>
</xsl:template>

</xsl:stylesheet>

编辑2:

  我应该为前4个设置h2-h5,之后设置为h6。

如果您的意思是想要将标题限制为最大h6而不管部分的深度如何,请更改此设置:

    <xsl:with-param name="depth" select="$depth + 1"/>

为:

    <xsl:with-param name="depth" select="$depth + ($depth &lt; 6)"/>