我有一个 xml 文档,其中包含类别列表:
<categories>
<category id="1" parent="0">Configurations</category>
<category id="11" parent="13">LCD Monitor</category>
<category id="12" parent="13">CRT Monitor</category>
<category id="13" parent="1"">Monitors</category>
<category id="123" parent="122">Printer</category>
...
</categories>
Run Code Online (Sandbox Code Playgroud)
以及产品清单:
<products>
<product>
...
<category>12</category>
...
</product>
...
</products>
Run Code Online (Sandbox Code Playgroud)
如果产品的类别等于 12,则应将其转换为“配置/监视器/CRT 监视器”(采用类别 12,然后是其父级 (13),依此类推)。如果parent为0,则停止。
有没有一种优雅的方法可以使用 XSL 转换来做到这一点?
我不知道这是否会被认为是优雅的,但是有了这个输入:
<root>
<categories>
<category id="1" parent="0">Configurations</category>
<category id="11" parent="13">LCD Monitor</category>
<category id="12" parent="13">CRT Monitor</category>
<category id="13" parent="1">Monitors</category>
<category id="123" parent="122">Printer</category>
</categories>
<products>
<product>
<category>12</category>
</product>
<product>
<category>11</category>
</product>
</products>
</root>
Run Code Online (Sandbox Code Playgroud)
这个 XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<root>
<xsl:apply-templates select="//product"/>
</root>
</xsl:template>
<xsl:template match="product">
<product>
<path>
<xsl:call-template name="catwalk">
<xsl:with-param name="id"><xsl:value-of select="category"/>
</xsl:with-param>
</xsl:call-template>
</path>
</product>
</xsl:template>
<xsl:template name="catwalk">
<xsl:param name="id"/>
<xsl:if test="$id != '0'">
<xsl:call-template name="catwalk">
<xsl:with-param name="id"><xsl:value-of select="//category[@id = $id]/@parent"/>
</xsl:with-param>
</xsl:call-template>
<xsl:value-of select="//category[@id = $id]"/><xsl:text>/</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
会给你这个输出:
<?xml version="1.0" encoding="utf-8"?>
<root>
<product>
<path>Configurations/Monitors/CRT Monitor/
</path>
</product>
<product>
<path>Configurations/Monitors/LCD Monitor/
</path>
</product>
</root>
Run Code Online (Sandbox Code Playgroud)
路径仍然有一个额外的尾部斜杠,您需要另外一点条件 XSLT 来使斜杠仅在您不在第一级时发出。
类别层次结构正确至关重要,否则您的转换很容易陷入无限循环,只有在内存耗尽时才会停止。如果我在真实系统中实现类似的东西,我会很想向 catWalk 模板添加一个参数,该参数在每次调用时都会递增,并将其添加到测试中,这样无论是否找到父级,它都会在 10 次调用后停止循环。