这是我之前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
的直接子元素。 - 每个
node
的name
属性连接起来以反映原始层次结构(请参阅前面的 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
,以修改最后一个node
的name
属性。但是,正如 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
元素都有子元素。