【问题标题】:optimize recursion in XSLT优化 XSLT 中的递归
【发布时间】:2017-12-19 10:39:51
【问题描述】:

我有以下 XML。它包含书籍和参考资料。一些参考文献可以追溯到第 1 册,例如第四册指第三册,第三册指第一册。

<?xml version="1.0" encoding="UTF-8"?>
<sandbox>
    <book xml:id="h1">
        <name>Book 1</name>
    </book>
    <book xml:id="h2">
        <name>Book 2</name>
    </book>
    <book xml:id="h3">
        <name>Book 3</name>
        <ref target="#h1"/>
    </book>
    <book xml:id="h4">
        <name>Book 4</name>
        <ref target="#h3"/>
    </book>
</sandbox>

我编写了以下 XSLT,它通过追溯对原始源的引用并添加相应的文本语句来丰富代码:

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

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

    <xsl:function name="sandbox:trace">
        <xsl:param name="target"/>
        <xsl:choose>
            <xsl:when test="document($target)/ref">
                <xsl:value-of select="sandbox:trace(document($target)/ref/@target)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="document($target)/name"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>

    <xsl:template match="ref">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:text>This book refers to </xsl:text>
            <xsl:value-of select="sandbox:trace(@target)"/>
            <xsl:text>!</xsl:text>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

它产生所需的输出:

<?xml version="1.0" encoding="UTF-8"?>
<sandbox>
    <book xml:id="h1">
        <name>Book 1</name>
    </book>
    <book xml:id="h2">
        <name>Book 2</name>
    </book>
    <book xml:id="h3">
        <name>Book 3</name>
        <ref target="#h1">This book refers to Book 1!</ref>
    </book>
    <book xml:id="h4">
        <name>Book 4</name>
        <ref target="#h3">This book refers to Book 1!</ref>
    </book>
</sandbox>

我的问题:这是一种“好”的方式还是更适合这项任务的解决方案?

【问题讨论】:

  • 一个观察:如果数据中有循环引用,您的代码将不会终止。

标签: xml xslt recursion xslt-2.0


【解决方案1】:

给定引用和 ID,我通常很想使用 xsl:keykey 函数,在您的情况下,因为输入使用 xml:id 属性,即使这不是必需的,因为您可以简单地使用 id 函数然后查找引用的元素。所以这似乎更简单:

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

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

    <xsl:function name="sandbox:check-ref" as="xs:string">
        <xsl:param name="target" as="element(book)"/>
        <xsl:sequence select="if ($target/ref)
                              then sandbox:check-ref($target/ref/id(substring(@target, 2)))
                              else $target/name"/>
    </xsl:function>

    <xsl:template match="ref">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:text>This book refers to </xsl:text>
            <xsl:value-of select="sandbox:check-ref(id(substring(@target, 2)))"/>
            <xsl:text>!</xsl:text>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

我还添加了类型注释,因为像 Michael Kay 这样的 XSLT 2 处理器的实现者通常指出这是一种提高类型安全性和代码性能的方法。

【讨论】:

    猜你喜欢
    • 2021-03-28
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 2016-07-28
    • 2010-12-03
    • 2014-06-23
    • 2014-01-10
    相关资源
    最近更新 更多