此XML的XSLT转换

时间:2013-06-12 14:36:22

标签: xml xslt transform

我有这个XML。

<?xml version="1.0" encoding="UTF-8"?>

<Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNameSpaceschemaLocation="browsenode.xsd">

    <Node>
        <node-id>1</node-id>
        <children count="2">
            <id> 2 </id>
            <id> 3 </id>
        </children>
    </Node>
    <Node>
        <node-id>2</node-id>
        <children count="1">
            <id> 4 </id>
        </children>
    </Node>
    <Node>
        <node-id>3</node-id>
        <children count="0">

        </children>
    </Node>
    <Node>
        <node-id>4</node-id>
        <children count="0">

        </children>
    </Node>
    <Node> 
        <node-id>5</node-id>
        <children count="0">

        </children>
    </Node>  
</Result>

我希望将其转换为

<?xml version="1.0" encoding="UTF-8"?>

<Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNameSpaceschemaLocation="browsenode.xsd">

    <Node>
        <node-id>1</node-id>
        <children count="2">
            <id> 2 </id>
            <id> 3 </id>
        </children>
    </Node>
    <Node>
        <node-id>2</node-id>
        <children count="1">
            <id> 4 </id>
        </children>
    </Node>
    <Node>
        <node-id>3</node-id>
        <children count="0">

        </children>
    </Node>
    <Node>
        <node-id>4</node-id>
        <children count="0">

        </children>
    </Node>
</Result>

即......给定一个node-id我想要所有可以从i到达的节点。顶级XML是树的扁平化版本。

我尝试使用这个XSLT。

    <?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

    <xsl:template name="root-matcher" match="/">
        <Result>
            <query>
                Query String
            </query>
        <xsl:call-template name="matcher">
            <xsl:with-param name="nodeValue" select="'1'" />
        </xsl:call-template>
        </Result>
    </xsl:template>

    <xsl:template name="matcher">
        <xsl:param name="nodeValue" />
        <xsl:if test="/Result/Node/node-id[text()=$nodeValue]">
            <Node>
                <browseNodeId>
                    <xsl:value-of select="/Result/Node/node-id" />
                </browseNodeId>
                <children>
                    <xsl:for-each select="/Result/Node/children/id">
                        <id>
                            <xsl:value-of select="." />
                        </id>
                    </xsl:for-each> 
                </children>
            </Node>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

有了这个,我只能达到一个等级。 1.我怎么递归呢?

我尝试添加                                                                        在匹配模板之后但是,它不起作用。

  1. 如何通过XSLT获得那些children =“2”或children =“0”属性?
  2. 我对XSLT非常新。事实上,我今天开始尝试理解。 请原谅,如果问题是天真的。欢迎任何资源/建议。 请建议

1 个答案:

答案 0 :(得分:2)

您请求的输出不会与您的xslt中继匹配。 据我所知,您希望输出中只有节点(<Node>)可以通过子ID访问,形成一个统计节点。

根据你的xlst你可以试试这个:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

    <xsl:template name="root-matcher" match="/">
        <Result >
            <query>
                Query String
            </query>
            <xsl:call-template name="matcher">
                <xsl:with-param name="nodeValue" select="'1'" />
            </xsl:call-template>

        </Result>
    </xsl:template>

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

    <xsl:template name="matcher">
        <xsl:param name="nodeValue" />
        <xsl:apply-templates select="//Node[node-id=$nodeValue]" mode="matcher" />
    </xsl:template>

    <xsl:template match="Node" mode="matcher">
        <xsl:copy>
            <xsl:apply-templates  />
        </xsl:copy>
        <xsl:for-each select="children/id">
            <xsl:apply-templates select="//Node[node-id=normalize-space(current()/.)]" mode="matcher" />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

我保留了根匹配和命名模板“matcher”,即使没有必要获取请求的输出。

将生成以下输出:

<Result>
    <query>
        Query String
    </query>
    <Node>
        <node-id>1</node-id>
        <children count="2">
            <id> 2 </id>
            <id> 3 </id>
        </children>
    </Node>
    <Node>
        <node-id>2</node-id>
        <children count="1">
            <id> 4 </id>
        </children>
    </Node>
    <Node>
        <node-id>4</node-id>
        <children count="0">

        </children>
    </Node>
    <Node>
        <node-id>3</node-id>
        <children count="0">

        </children>
    </Node>
</Result>

一些解释:
 <xsl:template match="@*|node()">这是最基本的xslt设计技术的递归Identity transform之一 同样优良的做法是使用apply-templates青睐for-each

<xsl:apply-templates select="//Node[node-id=$nodeValue]" mode="matcher" /> 这将查找文档中符合条件([node-id=$nodeValue])的所有Node元素:其中node-id的值与变量nodeValue中的值相同。

此处不需要使用模式。这使得模板可以匹配相同的节点但行为不同,具体取决于所使用的模式形式的调用者。

<xsl:apply-templates select="//Node[node-id=normalize-space(current()/.)]" mode="matcher" />这是对Node的Node模板的递归调用,其id与当前子ID相同。

请查看:w3.org