gpt4 book ai didi

xslt - 如何使用 XSLT 组装 XML 层次结构

转载 作者:行者123 更新时间:2023-12-01 01:18:12 24 4
gpt4 key购买 nike

鉴于此 XML

<Xml>
<Thing id="1" >
<Foo id="11" parentId="12"/>
<Foo id="12"/>
</Thing>
<Thing id="2" parentId="1" />
<Thing id="3" parentId="2" />
<Thing id="4">
<Foo id="11" parentId="15"/>
<Foo id="12" parentId="14"/>
<Foo id="13" parentId="11"/>
<Foo id="14" parentId="15"/>
<Foo id="15"/>
</Thing>
</Xml>


我想获取所有 sibling 的集合,并将它们组合成自己的层次结构。

每个具有 parentId 值的“事物”节点都应嵌套在相应的事物节点下。
每个具有 parentId 值的“Foo”节点都应该嵌套在相应的 Foo 节点下——但只能嵌套在其兄弟节点内。该示例有两组 Foo sibling 。

我正在尝试创建这个:

<Xml>
<Thing id="1" >
<Foo id="12">
<Foo id="11" parentId="12"/>
</Foo>
<Thing id="2" parentId="1" >
<Thing id="3" parentId="2" />
</Thing>
</Thing>
<Thing id="4" >
<Foo id="14" parentId="12">
<Foo id="12" parentId="14"/>
</Foo>
<Foo id="15">
<Foo id="11" parentId="15">
<Foo id="13" parentId="11"/>
</Foo>
</Foo>
</Thing>
</Xml>


这个例子很接近:
How can I use XSLT 1.0 to add structure to a non-heirarchal XML file?

我使用身份模板来保留所有节点和属性。然后我想要一个覆盖模板来匹配所有具有兄弟节点(后面或前面)的节点,以便兄弟节点的 @parentId 值等于我的 @id 值。我最接近的是硬编码一个 id/parentId 值来匹配。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output indent="yes"/>

<!-- override identity rule with template to match on
a node who has siblings, where sibling/@parentId == ./@id
-->
<xsl:template match="node()[@id='1' and (preceding-sibling::*[@parentId = 1] or following-sibling::*[@parentId = 1])]">
<captured>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</captured>
</xsl:template>


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


</xsl:stylesheet>


我看不到如何根据 parentId 值获取当前节点 @id 值以在 Xpath 匹配兄弟的谓词中使用。

然后我想在它下面嵌套当前节点的 sibling , sibling @ParentId 等于我的@id。

最佳答案

首先,请注意提供的 XML 文档 中的错误。 :

    <Foo id="12" parentId="14"/>
<Foo id="13" parentId="11"/>
<Foo id="14" parentId="12"/>
Foo之间存在循环关系与 id 12 和 Foo14 .这构成了一个循环,而不是“层次结构”。还有,这两个 Foo从层次结构的顶部无法访问元素! 请更正 .

本次改造 :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="kElemById" match="*"
use="concat(generate-id(..), '+', @id)"/>
<xsl:key match="*" name="kDescendants"
use="concat(generate-id(key('kElemById',
concat(generate-id(..), '+',@parentId))),
'+', @parentId)"/>

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

<xsl:template match="/*">
<Xml>
<xsl:apply-templates select="*[not(@parentId)]"/>
</Xml>
</xsl:template>

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

<xsl:apply-templates select="*[not(@parentId)]"/>

<xsl:apply-templates select=
"key('kDescendants', concat(generate-id(), '+', @id))"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

当应用于提供的 XML 文档时 :
<Xml>
<Thing id="1" >
<Foo id="11" parentId="12"/>
<Foo id="12"/>
</Thing>
<Thing id="2" parentId="1" />
<Thing id="3" parentId="2" />
<Thing id="4">
<Foo id="11" parentId="15"/>
<Foo id="12" parentId="14"/>
<Foo id="13" parentId="11"/>
<Foo id="14" parentId="12"/>
<Foo id="15"/>
</Thing>
</Xml>

产生正确的结果,排除任何无法访问的元素 :
<Xml>
<Thing id="1">
<Foo id="12">
<Foo id="11" parentId="12"/>
</Foo>
<Thing id="2" parentId="1">
<Thing id="3" parentId="2"/>
</Thing>
</Thing>
<Thing id="4">
<Foo id="15">
<Foo id="11" parentId="15">
<Foo id="13" parentId="11"/>
</Foo>
</Foo>
</Thing>
</Xml>

关于xslt - 如何使用 XSLT 组装 XML 层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10762376/

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