如何使用 XSLT 1.0 将平面 XML 结构转换为层次结构 XML?
How to translate a flat XML structure into hierarchical XML using XSLT 1.0?
从一个典型的、笨拙的格式 XML 结构开始:
<list>
<topic>
<title>
Paragraph 1
</title>
</topic>
<topic>
<main>
Content 1
</main>
</topic>
<topic>
<main>
Content 2
</main>
</topic>
<!-- ... -->
<topic>
<main>
Content n
</main>
</topic>
<topic>
<title>
Paragraph 2
</title>
</topic>
<topic>
<main>
Content 1
</main>
</topic>
<!-- ... -->
<topic>
<main>
Content n
</main>
</topic>
</list>
"title" 和 "main" 的内容只是占位符。
"title"的内容在每个节点都是不同的。
"main" 的内容可能会有所不同,也可能不会有所不同。
"main" 个元素的数量是不确定的。
目标是总结主题/标题元素之后的主题/主要元素,如下所示:
<list>
<paragraph name="1">
<item>Content 1</item>
<item>Content 2</item>
<item>Content n</item>
</paragraph>
<paragraph name="2">
<item>Content 1</item>
<item>Content n</item>
</paragraph>
</list>
边界条件是对 xslt 和 xpath 版本 1 的限制。
这个问题之前已经以类似的形式提出过。我没有找到满意的答案。
基本上,您正在寻找 group-starting-with
的 XSLT 1.0 实现。这可以按如下方式完成:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="topic-by-leader" match="topic[main]" use="generate-id(preceding-sibling::topic[title][1])" />
<xsl:template match="/list">
<xsl:copy>
<xsl:for-each select="topic[title]">
<paragraph name="{position()}">
<xsl:for-each select="key('topic-by-leader', generate-id())" >
<item>
<xsl:value-of select="normalize-space(main)" />
</item>
</xsl:for-each>
</paragraph>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
从一个典型的、笨拙的格式 XML 结构开始:
<list>
<topic>
<title>
Paragraph 1
</title>
</topic>
<topic>
<main>
Content 1
</main>
</topic>
<topic>
<main>
Content 2
</main>
</topic>
<!-- ... -->
<topic>
<main>
Content n
</main>
</topic>
<topic>
<title>
Paragraph 2
</title>
</topic>
<topic>
<main>
Content 1
</main>
</topic>
<!-- ... -->
<topic>
<main>
Content n
</main>
</topic>
</list>
"title" 和 "main" 的内容只是占位符。 "title"的内容在每个节点都是不同的。 "main" 的内容可能会有所不同,也可能不会有所不同。 "main" 个元素的数量是不确定的。
目标是总结主题/标题元素之后的主题/主要元素,如下所示:
<list>
<paragraph name="1">
<item>Content 1</item>
<item>Content 2</item>
<item>Content n</item>
</paragraph>
<paragraph name="2">
<item>Content 1</item>
<item>Content n</item>
</paragraph>
</list>
边界条件是对 xslt 和 xpath 版本 1 的限制。
这个问题之前已经以类似的形式提出过。我没有找到满意的答案。
基本上,您正在寻找 group-starting-with
的 XSLT 1.0 实现。这可以按如下方式完成:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="topic-by-leader" match="topic[main]" use="generate-id(preceding-sibling::topic[title][1])" />
<xsl:template match="/list">
<xsl:copy>
<xsl:for-each select="topic[title]">
<paragraph name="{position()}">
<xsl:for-each select="key('topic-by-leader', generate-id())" >
<item>
<xsl:value-of select="normalize-space(main)" />
</item>
</xsl:for-each>
</paragraph>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>