将多个节点与嵌套节点合并

发布于 2024-10-25 00:49:25 字数 1456 浏览 1 评论 0原文

我是 XSL 的新手,但我需要 XSL 文件,将具有相同名称属性的节点合并到一个元素中 - 并且对子节点执行相同的操作 - 如果存在具有不同名称的节点,则将其作为它的一个示例XML 如下。

<?xml version="1.0" encoding="UTF-8"?>
<test>
    <component name="root">
        <component name="c2">
            <component name="c3">
                <component name="c4" />
            </component>
        </component>
    </component>
    <component name="root">
        <component name="c2">
            <component name="A4" />
        </component>
        <component name="root">
            <component name="A3" />
        </component>
        <component name="root">
            <component name="X1">
                <component name="X2" />
            </component>
        </component>
    </component>
    <component name="difRoot">
    </component>
</test>

期望的输出如下

<output>
<component name="root">
    <component name="c2">
        <component name="c3">
            <component name="c4"/>
        </component>
        <component name="A4"/>
    </component>
    <component name="A3"/>
          <component name="X1">
                 <component name="X2"/>
          </component>
</component>
<component name="difRoot"/>
</output>

谢谢

I am newbie in XSL ,but i need XSL file that merge nodes with the same name attribute into one element-and the same done for the son nodes-, and if there is nodes' with different names it put as it , a example of XML is as follows .

<?xml version="1.0" encoding="UTF-8"?>
<test>
    <component name="root">
        <component name="c2">
            <component name="c3">
                <component name="c4" />
            </component>
        </component>
    </component>
    <component name="root">
        <component name="c2">
            <component name="A4" />
        </component>
        <component name="root">
            <component name="A3" />
        </component>
        <component name="root">
            <component name="X1">
                <component name="X2" />
            </component>
        </component>
    </component>
    <component name="difRoot">
    </component>
</test>

The desired output is as follows

<output>
<component name="root">
    <component name="c2">
        <component name="c3">
            <component name="c4"/>
        </component>
        <component name="A4"/>
    </component>
    <component name="A3"/>
          <component name="X1">
                 <component name="X2"/>
          </component>
</component>
<component name="difRoot"/>
</output>

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

内心荒芜 2024-11-01 00:49:25

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kComponentByName" match="component" use="@name"/>
    <xsl:template match="test">
        <output>
            <xsl:call-template name="merge">
                <xsl:with-param name="pSequence" select="*"/>
            </xsl:call-template>
        </output>
    </xsl:template>
    <xsl:template name="merge">
        <xsl:param name="pSequence" select="/.."/>
        <xsl:if test="$pSequence">
            <xsl:variable name="vName" select="$pSequence[1]/@name"/>
            <xsl:for-each select="$pSequence[1]">
                <xsl:copy>
                    <xsl:copy-of select="@*"/>
                    <xsl:call-template name="merge">
                        <xsl:with-param name="pSequence"
                             select="key('kComponentByName',$vName)
                                        /component[@name != $vName]"/>
                    </xsl:call-template>
                </xsl:copy>
            </xsl:for-each>
            <xsl:call-template name="merge">
                <xsl:with-param name="pSequence"
                     select="$pSequence[@name != $vName]"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

输出:

<output>
    <component name="root">
        <component name="c2">
            <component name="c3">
                <component name="c4" />
            </component>
            <component name="A4" />
        </component>
        <component name="A3" />
        <component name="X1">
            <component name="X2" />
        </component>
    </component>
    <component name="difRoot" />
</output>

注意:递归层次结构未完全解决,仅阻止我自己作为孩子。

更新:命名模板说明:如果pSequence不为空,则获取第一个节点,然后复制自身并将模板应用于所有组件的子节点具有相同 @name 的元素(也过滤具有此 @name 的元素);最后调用自身过滤与已处理元素具有相同@namecomponent元素的pSequence。因此,它逐级、逐节点过滤兄弟姐妹和子代。完全的循环预防应该是传递带有祖先名称的序列以便进行过滤。剩下的就是练习了...

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kComponentByName" match="component" use="@name"/>
    <xsl:template match="test">
        <output>
            <xsl:call-template name="merge">
                <xsl:with-param name="pSequence" select="*"/>
            </xsl:call-template>
        </output>
    </xsl:template>
    <xsl:template name="merge">
        <xsl:param name="pSequence" select="/.."/>
        <xsl:if test="$pSequence">
            <xsl:variable name="vName" select="$pSequence[1]/@name"/>
            <xsl:for-each select="$pSequence[1]">
                <xsl:copy>
                    <xsl:copy-of select="@*"/>
                    <xsl:call-template name="merge">
                        <xsl:with-param name="pSequence"
                             select="key('kComponentByName',$vName)
                                        /component[@name != $vName]"/>
                    </xsl:call-template>
                </xsl:copy>
            </xsl:for-each>
            <xsl:call-template name="merge">
                <xsl:with-param name="pSequence"
                     select="$pSequence[@name != $vName]"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Output:

<output>
    <component name="root">
        <component name="c2">
            <component name="c3">
                <component name="c4" />
            </component>
            <component name="A4" />
        </component>
        <component name="A3" />
        <component name="X1">
            <component name="X2" />
        </component>
    </component>
    <component name="difRoot" />
</output>

Note: Recursive hierarchy is not fully addressed, only prevents myself as child.

Update: Named template explanation: if pSequence isn't empty, take the first node then copy itself and apply templates to children of all the component elements with the same @name (filtering those with this @name also); lastly call itself filtering pSequence of the component elements with the same @name as the processed one. So, it goes level by level and node by node filtering siblings and children. Full circularity preventions should be do it passing a sequence with ancestors names in order to filter. That's left as exercise...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文