我有像这样的xml文件:
<root>
<scenario name="film1">
<case name="aaa">
<test name="test1">ok</test>
</case>
<case name="bbb">
<test name="test2">not ok</test>
</case>
<case name="aaa">
<test name="test3">not ok</test>
</case>
<case name="bbb">
<test name="test66">ok</test>
</case>
</scenario>
</root>
当然有更多的节点,比如场景,但我希望每个场景都有case
组。
我期待类似的东西:
<root>
<scenario name="fil1">
<case name="aaa">
<test name="test1">ok</test>
<test name="test3">not ok</test>
</case>
<case name="bbb">
<test name="test2">not ok</test>
<test name="test66">ok</test>
</case>
</scenario>
</root>
我制作了xslt文件:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="scenario">
<scenario>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:apply-templates/>
</scenario>
</xsl:template>
<xsl:template match ="case">
<case>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
</case>
</xsl:template>
</xsl:stylesheet>
你知道我现在应该做什么吗?
答案 0 :(得分:0)
我会用这样的东西......
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="scenario">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match ="case">
<xsl:param name="thisName">
<xsl:value-of select="@name" />
</xsl:param>
<xsl:if test=".=/root/scenario/case[@name=$thisName][1]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="/root/scenario/case[@name=$thisName]/test" />
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match ="test">
<xsl:copy>
<xsl:apply-templates select="@*" />
</xsl:copy>
</xsl:template>
<xsl:template match ="@*">
<xsl:copy />
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
xslt 1.0中的标准方法 - muenchian分组。
C-u 10 C-x e
答案 2 :(得分:0)
您在问题中说,您希望为每个case
分组scenario
。如果您确实有多个scenario
元素,并希望将每个元素中的case
元素分组,则需要使用连接键:
<xsl:key name="case" match="case" use="concat(../@name, '|', @name)" />
这意味着,如果您有两个case
元素具有相同的name
,但在不同的scenario
元素中,则它们仍然会被单独分组。
现在,对于分组,对于case
中的每个scenario
语句,您需要找到键中为其给定属性首先出现的case
元素。这可以按如下方式完成:
<xsl:apply-templates select="case[generate-id() = generate-id(key('case', concat(../@name, '|', @name))[1])]" />
要分解......
key('case', concat(../@name, '|', @name))
- 获取具有相同属性的所有元素
key('case', concat(../@name, '|', @name))[1]
- 获取该列表的第一个元素
generate-id(key('case', concat(../@name, '|', @name))[1])
- 为第一个元素生成唯一ID,因此可以将其与当前元素进行比较。
所以,实际上,你得到了不同的元素。然后,您可以再次使用密钥获取“组”中的项目
<xsl:for-each select="key('case', concat(../@name, '|', @name))">
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="case" match="case" use="concat(../@name, '|', @name)" />
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="scenario">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="case[generate-id() = generate-id(key('case', concat(../@name, '|', @name))[1])]" />
</xsl:copy>
</xsl:template>
<xsl:template match ="case">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each select="key('case', concat(../@name, '|', @name))">
<xsl:apply-templates />
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
正如评论中所提到的,关于这种方法的权威性文章可以在http://www.jenitennison.com/xslt/grouping/muenchian.html找到,所以值得一读,然后重新阅读,然后练习,直到你最终理解它为止。
另外,请注意Identity Transform的使用,这意味着如果您只想在不做更改的情况下复制它,则不必为每个特定元素编写模板。