递归连接父属性 - 并保留元素数据



这是我之前SO问题的后续。事实证明,我使我的最小测试用例太小了。

给定以下 XML:

<package>
    <node name="a">
        <node name="b">
            <author>John Doe</author>
            <date>2015-12-15</date>
        </node>
        <node name="c">
            <author>Franzis Cooper</author>
            <date>2014-09-08</date>
        </node>
        <node name="d">
            <node name="e">
                <author>Some dude</author>
                <date>2015-02-18</date>
            </node>
            <node name="f">
                <author>Max Planck</author>
                <date>1858-04-23</date>
            </node>
            <node name="g">
                <node name="h">
                    <author>Jane Doe</author>
                    <date>2019-07-15</date>
                </node>
            </node>    
        </node>
    </node>
</package>

我想应用一个 XSL 转换,该转换会产生以下结果:

  • 所有node都展平了(例如,所有node元素都是package的直接子元素。
  • 每个nodename 属性连接起来以反映原始层次结构(请参阅前面的 SO 问题(。
  • 保留
  • /复制原始树层次结构中最后一个node的数据(没有进一步node子级的node(。

例如,应用转换后,上面发布的 XML 输入应如下所示:

<package>
    <node name="a-b">
        <author>John Doe</author>
        <date>2015-12-15</date>
    </node>
    <node name="a-c">
        <author>Franzis Cooper</author>
        <date>2014-09-08</date>
    </node>
    <node name="a-d-e">
        <author>Some dude</author>
        <date>2015-02-18</date>
    </node>
    <node name="a-d-f">
        <author>Max Planck</author>
        <date>1858-04-23</date>
    </node>
    <node name="a-d-g-h">
        <author>Jane Doe</author>
        <date>2019-07-15</date>
    </node>
</package>

最初的问题帮助我展平树并正确连接name属性。我以此为起点并对其进行了修改,以便保留最终node的数据:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <!-- Identity transformation -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <!-- Transform each node -->
    <xsl:template match="node[*]">
        <xsl:apply-templates/>
    </xsl:template>
    <!-- Modify the 'name' attribute of each node that doesn't have a child -->
    <xsl:template match="node[not(*)]/@name">
        <xsl:attribute name="name" select="string-join(../ancestor-or-self::node/@name, '-')"/>
    </xsl:template>
</xsl:stylesheet>

我遇到的问题是转换将复制node的数据(例如author元素(,但随后省略node元素本身。

我假设我可以简单地在模板中调用xsl:copy-of,以修改最后一个nodename属性。但是,正如 XSLT 处理器告诉我的那样,这是不可能的。

我对 XSLT 非常陌生,学习曲线似乎相当陡峭。我将不胜感激在这方面的任何帮助。

XSLT 2.0 可用。

模式node[*]不仅匹配要删除的node元素,还匹配要保留的元素。尝试更改:

<xsl:template match="node[*]">
    <xsl:apply-templates/>
</xsl:template>

自:

<xsl:template match="node[*/*]">
    <xsl:apply-templates/>
</xsl:template>

或:

<xsl:template match="node[node]">
    <xsl:apply-templates/>
</xsl:template>

此外,我相信您的最后一个模板需要:

<xsl:template match="node[not(node)]/@name">
    <xsl:attribute name="name" select="string-join(../ancestor-or-self::node/@name, '-')"/>
</xsl:template>

或只是:

<xsl:template match="@name">
    <xsl:attribute name="name" select="string-join(../ancestor-or-self::node/@name, '-')"/>
</xsl:template>

您现在拥有的内容与输入中的任何内容都不匹配,因为(再次(所有node元素都有子元素。

最新更新