gpt4 book ai didi

xml - XSLT 1.0 : Duplicate structures and substructures simultaneously

转载 作者:行者123 更新时间:2023-12-04 08:13:15 24 4
gpt4 key购买 nike

感谢您的时间。我会尽量保持简短,切中要点。
我的目标是使用 XSLT 1.0 转换 XML 文件,使其复制特定节点。问题是,我需要复制也需要复制的结构的子结构。我希望下面的例子能让我的问题变得清晰。
这里是源 XML:

<?xml version="1.0" encoding="UTF-8"?>
<parent_node>
<derived_from_a>
<element1>test</element1>
<element2>test</element2>
</derived_from_a>
<derived_from_b>
<element1>test</element1>
<element2>test</element2>
<derived_from_c>
<element3>test</element3>
<element4>test</element4>
</derived_from_c>
</derived_from_b>
</parent_node>
编辑:我需要所有 <derived_from_a>要复制到名为 <a> 的新节点中的节点.节点 <derived_from_b> 也应该发生同样的情况和 <derived_from_c>对于新节点 <b><c> .
这是所需的输出:
<?xml version="1.0" encoding="UTF-8"?>
<parent_node>
<derived_from_a>
<element1>test</element1>
<element2>test</element2>
</derived_from_a>
<a>
<element1>test</element1>
<element2>test</element2>
</a>
<derived_from_b>
<element1>test</element1>
<element2>test</element2>
<derived_from_c>
<element3>test</element3>
<element4>test</element4>
</derived_from_c>
<c>
<element3>test</element3>
<element4>test</element4>
</c>
</derived_from_b>
<b>
<element1>test</element1>
<element2>test</element2>
<derived_from_c>
<element3>test</element3>
<element4>test</element4>
</derived_from_c>
<c>
<element3>test</element3>
<element4>test</element4>
</c>
</b>
</parent_node>
请注意,我正在复制节点 <derived_from_c>进入 <c>在两个父结构中( <derived_from_b><b> )。这就是我需要的。
我写了以下 XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- -->
<xsl:template match="//derived_from_a">
<!-- first copy structure with original name -->
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<!-- then duplicate it -->
<a>
<xsl:copy-of select="child::node()"/>
</a>
</xsl:template>
<xsl:template match="//derived_from_b">
<!-- first copy structure with original name -->
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<!-- then duplicate it -->
<b>
<xsl:copy-of select="child::node()"/>
</b>
</xsl:template>
<xsl:template match="//derived_from_c">
<!-- first copy structure with original name -->
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<!-- then duplicate it -->
<c>
<xsl:copy-of select="child::node()"/>
</c>
</xsl:template>
</xsl:stylesheet>
这会生成以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<parent_node>
<derived_from_a>
<element1>test</element1>
<element2>test</element2>
</derived_from_a>
<a>
<element1>test</element1>
<element2>test</element2>
</a>
<derived_from_b>
<element1>test</element1>
<element2>test</element2>
<derived_from_c>
<element3>test</element3>
<element4>test</element4>
</derived_from_c>
<c>
<element3>test</element3>
<element4>test</element4>
</c>
</derived_from_b>
<b>
<element1>test</element1>
<element2>test</element2>
<derived_from_c>
<element3>test</element3>
<element4>test</element4>
</derived_from_c>
</b>
</parent_node>
注意节点 <c>只存在于节点 <derived_from_b> .不在节点 <b> .
我试过移动 <derived_from_c>转换到我的 XSLT 顶部没有成功。
有没有一种方法可以在一个映射中复制所有内容?
谢谢!
你好,
缺口

最佳答案

这个 XSLT 1.0 转换给出了您正在寻找的结果:

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

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

<xsl:template match="*[starts-with(name(), 'derived_from_')]">
<xsl:call-template name="identity" />
<xsl:element name="{substring-after(name(), 'derived_from_')}">
<xsl:apply-templates select="node() | @*" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<parent_node>
<derived_from_a>
<element1>test</element1>
<element2>test</element2>
</derived_from_a>
<a>
<element1>test</element1>
<element2>test</element2>
</a>
<derived_from_b>
<element1>test</element1>
<element2>test</element2>
<derived_from_c>
<element3>test</element3>
<element4>test</element4>
</derived_from_c>
</derived_from_b>
<b>
<element1>test</element1>
<element2>test</element2>
<derived_from_c>
<element3>test</element3>
<element4>test</element4>
</derived_from_c>
<c>
<element3>test</element3>
<element4>test</element4>
</c>
</b>
</parent_node>
这里的技巧是给身份模板一个 match和一个 name .这样,它既可以在 XSLT 处理器遍历您的输入文档时以“拉式”调用,也可以通过 <xsl:call-template> 手动调用。 .
手动调用使我们能够处理当前节点的后代,而不仅仅是复制它们,这满足了您“复制也需要复制的结构的子结构”的要求。

如果您的输出元素名称( <a> )实际上不是您的输入元素名称( <derived_from_a> )的子字符串,您可能会试图复制工作模板。
为了避免这种重复,您可以将映射嵌入到自定义元素中的 XSLT 中,并通过 document('') 使用自引用。动态提取新名称:
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://tempuri.org"
>
<my:map>
<name from="derived_from_a" to="x" />
<name from="derived_from_b" to="y" />
<name from="derived_from_c" to="z" />
</my:map>

<!-- ... -->

<xsl:template match="derived_from_a|derived_from_b|derived_from_c">
<!-- ... -->
<xsl:element name="{document('')/*/my:map/name[@from = name(current())]/@to}">
<!-- ... -->
</xsl:element>
</xsl:template>
</xsl:stylesheet>
使用自定义元素添加配置有时非常有用。另一种选择是通过 <xsl:param> 传入映射。来自调用代码,具体取决于您使用的 XSLT 工具的功能。第三个选项是使用 <xsl:variable>包含 <xsl:choose>确定新元素名称。

关于xml - XSLT 1.0 : Duplicate structures and substructures simultaneously,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65842248/

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