使用XSLT在同一文档中处理XSLT输出,将平面数据输出到树节点集

时间:2017-01-02 21:07:58

标签: xml xslt xpath

让我先从一个例子开始,然后按照自己的方式解决问题。这是一个非常简单和干净的XML数据:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="flatdata.xsl"?>

<db>
<item>
    <parent></parent>
    <id>1</id>
    <title>lorem ipsum</title>
</item>

<item>
    <parent></parent>
    <id>2</id>
    <title>dolor sit amet</title>
</item>

<item>
    <parent>1</parent>
    <id>3</id>
    <title>consectetur adipiscing elit.</title>
</item>

<item>
    <parent>1</parent>
    <id>4</id>
    <title>Nunc varius tempus sem et fringilla</title>
</item>

<item>
    <parent>2</parent>
    <id>5</id>
    <title>Aenean egestas</title>
</item>

<item>
    <parent>2</parent>
    <id>6</id>
    <title>turpis vel placerat suscipit</title>
</item>

<item>
    <parent>5</parent>
    <id>7</id>
    <title>ligula nulla consequat justo</title>
</item>
</db>

这是一个项目的平面数据库,其中包含一个由<parent>关系给出的树形结构。

将此转换为嵌套结构以显示item的树关系的XSLT非常简单(我完成了我的作业):

<xsl:stylesheet version="1.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <html>
        <body>
            <xsl:apply-templates select="db"/>
        </body>
    </html>
</xsl:template>

<xsl:template match="db">
    <ul>
        <xsl:apply-templates select="item[parent='']"/>
    </ul>
</xsl:template>

<xsl:template match="item">
    <xsl:variable name="vId" select="id"/>
    <xsl:variable name="vChildren" select="../item[parent=$vId]"/>
    <li>
        <b><xsl:value-of select="concat(id,': ')"/></b> <xsl:value-of select="title"/>
        <xsl:if test="$vChildren">
            <ul>
                <xsl:apply-templates select="$vChildren"/>
            </ul>
        </xsl:if>
    </li>
</xsl:template>
</xsl:stylesheet>

产生以下输出:

<ul>
<li>
    <b>1: </b>lorem ipsum
    <ul>
        <li><b>3: </b>consectetur adipiscing elit.</li>
        <li><b>4: </b>Nunc varius tempus sem et fringilla</li>
    </ul>
</li>
<li>
    <b>2: </b>dolor sit amet
    <ul>
        <li>
            <b>5: </b>Aenean egestas
            <ul>
                <li>
                    <b>7: </b>ligula nulla consequat justo
                </li>
            </ul>
        </li>
        <li>
            <b>6: </b>turpis vel placerat suscipit
        </li>
    </ul>
</li>
</ul>

情况是这个嵌套(树)结构更方便使用XSLT处理我的目的。我可以使用简单的XPath等来分析哪个item有多少后代等等。我从源头收到的XML数据是平的,我无能为力。

那么,怎么可以

  1. 识别和创建树结构是某种格式(当然不是必须是HTML,它不可避免地是某种内部格式,或节点集?)和
  2. 在同一样式表上进一步处理具有XSLT本身的树?
  3. 我试图在现代浏览器上通过XSLT显示flatdata基础结果,所以我想这意味着我被1.0卡住了(对吧?)。

1 个答案:

答案 0 :(得分:0)

您可以在任何版本的XSLT中创建全局变量<xsl:variable name="rtf"><xsl:apply-templates/></xsl:variable>,但是在XSLT 1.0中,您将拥有一个结果树片段,您只能使用xsl:copy-of输出但不能使用XPath导航,除非您在exsl:node-set中使用<xsl:variable name="ns" select="exsl:node-set($rtf)" xmlns:exsl="http://exslt.org/common"/>之类的扩展功能。然而,由于IE和Edge不支持exsl:node-set,只有在不同命名空间(msxsl:node-set)中的专有xmlns:msxsl="urn:schemas-microsoft-com:xslt",因此在内部浏览器中出现问题。使用扩展函数可以欺骗IE识别exsl:node-set,但该方法在Edge中不起作用。因此,在跨浏览器的XSLT 1.0中,您只需使用xsl:choose/xsl:when/xsl:if进行测试即可。 function-available('exsl:node-set')支持哪个函数将结果树片段转换为节点集。

作为替代方案,您可以查看Saxon-CE或Saxon-JS,将XSLT 2.0引入到不存在结果树片段限制的浏览器中。