我有这个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.我怎么递归呢?
我尝试添加 在匹配模板之后但是,它不起作用。
我对XSLT非常新。事实上,我今天开始尝试理解。 请原谅,如果问题是天真的。欢迎任何资源/建议。 请建议
答案 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