gpt4 book ai didi

xml - 从 XSLT 中的路径创建嵌套树结构

转载 作者:数据小太阳 更新时间:2023-10-29 01:42:53 25 4
gpt4 key购买 nike

我有一个动态 XML 文档,它表示类别的树结构,但是使用路径分隔属性以任意顺序来实现 - 就像这样:

   <data>    
<record ID="24" Name="category 1\sub category 1"/>
<record ID="26" Name="category 1"/>
<record ID="25" Name="category 1\sub category 1\sub category 2"/>
<record ID="27" Name="category 1\sub category 1\sub category 3"/>
...
</data>

我需要想出一个“规范化”XML 的解决方案,以便将其转换成如下形式:

   <data>    
<record ID="26" Name="category 1">
<record ID="24" Name="sub category 1">
<record ID="25" Name="sub category 2"/>
<record ID="27" Name="sub category 3"/>
</record>
</record>
...
</data>

基本上,我想知道这是否是 XSLT 可能能够解决的问题,以及如何解决,而不必通过编程来解决。

最佳答案

当然,没问题:

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

<xsl:output indent="yes" />

<xsl:template match="/data">
<!-- copy the document element -->
<xsl:copy>
<!-- That's where we start: all "record" nodes that have no "\". -->
<xsl:apply-templates mode="recurse" select="/data/record[
not(contains(@Name, '\'))
]" />
</xsl:copy>
</xsl:template>

<xsl:template match="record" mode="recurse">
<xsl:param name="starting-path" select="''" />

<!-- The record node and its ID attribute can be copied. -->
<xsl:copy>
<xsl:copy-of select="@ID" />

<!-- Create the new "name" attribute. -->
<xsl:attribute name="Name">
<xsl:value-of select="substring-after(@Name, $starting-path)" />
</xsl:attribute>

<!-- Append a backslash to the current path. -->
<xsl:variable name="current-path" select="concat(@Name, '\')" />

<!-- Select all "record" nodes that are one level deeper... -->
<xsl:variable name="children" select="/data/record[
starts-with(@Name, $current-path)
and
not(contains(substring-after(@Name, $current-path), '\'))
]" />

<!-- ...and apply this template to them. -->
<xsl:apply-templates mode="recurse" select="$children">
<xsl:with-param name="starting-path" select="$current-path" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

我的系统输出:

<data>
<record ID="26" Name="category 1">
<record ID="24" Name="sub category 1">
<record ID="25" Name="sub category 2"></record>
<record ID="27" Name="sub category 3"></record>
</record>
</record>
</data>

请注意,整个解决方案基于所有路径都是规范的并且不包含尾随反斜杠的假设。

另请注意,任何不匹配/孤立的“记录”元素都不会出现在输出中(当然,除非它们位于根级别)。

还有一件事:模板模式(“递归”)并不是绝对必要的。我包含它是因为模板正在做一些相当特别的事情,并且您的解决方案中可能有另一个模板匹配“记录”节点。在这种情况下,可以在不破坏其他任何东西的情况下加入这个解决方案。对于独立解决方案,可以随时删除模板模式。

哦,还有最后一件事:如果您希望结果文档按名称排序,请包含一个 <xsl:sort> element。与 <xsl:apply-templates> (两次都出现),像这样:

<xsl:apply-templates select="...">
<xsl:sort select="@Name" data-type="text" order="ascending" />
</xsl:apply-templates>

关于xml - 从 XSLT 中的路径创建嵌套树结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/872067/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com