xslt 将父级 -> 子级更改为子级 -> 父级
xslt change parent -> child to child -> parent
我有一个像这样的 XML,需要用他们的位置改变 parent->child:
<root>
<testcase name="Case1">
<testsuite>Suite1</testsuite>
</testcase>
<testcase name="Case2">
<testsuite>Suite1</testsuite>
</testcase>
<testcase name="Case3">
<testsuite>Suite2</testsuite>
</testcase>
<testcase name="Case4">
<testsuite>Suite2</testsuite>
</testcase>
</root>
需要将其转换为 xml:
<root>
<testsuite name="Suite1">
<testcase>Case1</testcase>
<testcase>Case2</testcase>
</testsuite>
<testsuite name="Suite2">
<testcase>Case3</testcase>
<testcase>Case4</testcase>
</testsuite>
</root>
任何人都可以帮助实现这个吗?
这是分组问题的示例,与大多数分组问题一样,首选方法(至少在 XSLT 1.0 中)是使用 Muenchian 分组:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="kSuite" match="testsuite" use="."/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates
select="testcase/testsuite[generate-id() =
generate-id(key('kSuite', .)[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="testsuite">
<testsuite name="{.}">
<xsl:apply-templates select="key('kSuite', .)/.." />
</testsuite>
</xsl:template>
<xsl:template match="testcase">
<xsl:copy>
<xsl:value-of select="@name" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当这是 运行 样本输入时,结果是:
<root>
<testsuite name="Suite1">
<testcase>Case1</testcase>
<testcase>Case2</testcase>
</testsuite>
<testsuite name="Suite2">
<testcase>Case3</testcase>
<testcase>Case4</testcase>
</testsuite>
</root>
借助像 Saxon 9 或 XmlPrime 这样的 XSLT 2.0 处理器,您可以使用
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:for-each-group select="*/*" group-by=".">
<xsl:copy>
<xsl:attribute name="name" select="."/>
<xsl:apply-templates select="current-group()/.."/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/*">
<xsl:element name="{name()}">
<xsl:value-of select="@name"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
我有一个像这样的 XML,需要用他们的位置改变 parent->child:
<root>
<testcase name="Case1">
<testsuite>Suite1</testsuite>
</testcase>
<testcase name="Case2">
<testsuite>Suite1</testsuite>
</testcase>
<testcase name="Case3">
<testsuite>Suite2</testsuite>
</testcase>
<testcase name="Case4">
<testsuite>Suite2</testsuite>
</testcase>
</root>
需要将其转换为 xml:
<root>
<testsuite name="Suite1">
<testcase>Case1</testcase>
<testcase>Case2</testcase>
</testsuite>
<testsuite name="Suite2">
<testcase>Case3</testcase>
<testcase>Case4</testcase>
</testsuite>
</root>
任何人都可以帮助实现这个吗?
这是分组问题的示例,与大多数分组问题一样,首选方法(至少在 XSLT 1.0 中)是使用 Muenchian 分组:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="kSuite" match="testsuite" use="."/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates
select="testcase/testsuite[generate-id() =
generate-id(key('kSuite', .)[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="testsuite">
<testsuite name="{.}">
<xsl:apply-templates select="key('kSuite', .)/.." />
</testsuite>
</xsl:template>
<xsl:template match="testcase">
<xsl:copy>
<xsl:value-of select="@name" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当这是 运行 样本输入时,结果是:
<root>
<testsuite name="Suite1">
<testcase>Case1</testcase>
<testcase>Case2</testcase>
</testsuite>
<testsuite name="Suite2">
<testcase>Case3</testcase>
<testcase>Case4</testcase>
</testsuite>
</root>
借助像 Saxon 9 或 XmlPrime 这样的 XSLT 2.0 处理器,您可以使用
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:for-each-group select="*/*" group-by=".">
<xsl:copy>
<xsl:attribute name="name" select="."/>
<xsl:apply-templates select="current-group()/.."/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/*">
<xsl:element name="{name()}">
<xsl:value-of select="@name"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>