输入XML:
<root>
<com>
<head>A</head>
<body>Type A</body>
</com>
<com>
<head>B</head>
<body>Type B</body>
</com>
<com>
<head>C</head>
<body>Type C</body>
</com>
<com>
<head>D</head>
<body>Type D</body>
</com>
<com>
<body>Type No</body>
</com>
<plom>xml type X</plom>
<plom>xml type Y</plom>
<com>
<head>a</head>
<body>Type a</body>
</com>
<com> <head>b</head>
<body>Type c</body>
</com>
</root>
必需的输出XML:
<root>
<l>
<li>
<lab>A</lab>
<text>Type A</text>
</li>
<li>
<lab>B</lab>
<text>Type B</text>
</li>
<li>
<lab>C</lab>
<text>Type C</text>
</li>
<li>
<lab>D</lab>
<text>Type D</text>
</li>
</l>
<p>Type No</p>
<p>xml type X</p>
<p>xml type Y</p>
<l>
<li>
<lab>a</lab>
<text>Type a</text>
</li>
<li>
<lab>b</lab>
<text>Type b</text>
</li>
</l>
</root>
请帮助我从上面显示的输入中获取所需的输出。要求是:如果 com / head 即将到来,则应在 l / li 中输出。但是当找到除<com>
或<com>
以外的任何元素({1}}时,该元素应该关闭,该元素变为<l>
,再次 com / head 遇到b>,应该创建<p>
。
答案 0 :(得分:0)
<强>予。这个XSLT 2.0转换:
<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="*"/>
<xsl:template match="/">
<root>
<xsl:for-each-group select="/*/*"
group-adjacent="boolean(self::com/head)">
<xsl:apply-templates select="current-group()[1]">
<xsl:with-param name="pGroup" select="current-group()"/>
</xsl:apply-templates>
</xsl:for-each-group>
</root>
</xsl:template>
<xsl:template match="com[head]">
<xsl:param name="pGroup"/>
<l>
<xsl:apply-templates select="$pGroup" mode="inGroup"/>
</l>
</xsl:template>
<xsl:template match="com[head]" mode="inGroup">
<li>
<lab><xsl:value-of select="head"/></lab>
<type><xsl:value-of select="body"/></type>
</li>
</xsl:template>
<xsl:template match="*[not(self::com/head)]">
<xsl:param name="pGroup"/>
<xsl:apply-templates select="$pGroup" mode="inGroup"/>
</xsl:template>
<xsl:template match="*[not(self::com/head)]" mode="inGroup">
<p><xsl:value-of select="."/></p>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<root>
<com>
<head>A</head>
<body>Type A</body>
</com>
<com>
<head>B</head>
<body>Type B</body>
</com>
<com>
<head>C</head>
<body>Type C</body>
</com>
<com>
<head>D</head>
<body>Type D</body>
</com>
<com>
<body>Type No</body>
</com>
<plom>xml type X</plom>
<plom>xml type Y</plom>
<com>
<head>a</head>
<body>Type a</body>
</com>
<com>
<head>b</head>
<body>Type b</body>
</com>
</root>
生成想要的正确结果:
<root>
<l>
<li>
<lab>A</lab>
<type>Type A</type>
</li>
<li>
<lab>B</lab>
<type>Type B</type>
</li>
<li>
<lab>C</lab>
<type>Type C</type>
</li>
<li>
<lab>D</lab>
<type>Type D</type>
</li>
</l>
<p>Type No</p>
<p>xml type X</p>
<p>xml type Y</p>
<l>
<li>
<lab>a</lab>
<type>Type a</type>
</li>
<li>
<lab>b</lab>
<type>Type b</type>
</li>
</l>
</root>
<强>解释强>:
使用<xsl:for-each-group group-adjacent="...">
。选定的相邻元素组对boolean(self::com/head)
具有相同的值 - 全部为true()
或全部为false()
。
仅指定每组中第一个元素的处理,并将该组中所有元素的序列作为参数提供。
匹配具有子com
的元素head
的模板(仅当它是组中的第一个元素时才选择执行),包装处理元素的所有结果在l
元素中的组中,然后以模式inGroup
启动对组中各个元素的处理。
匹配任何其他模板的模板(不是具有com
子元素的head
元素(仅当这是组中的第一个元素时才选择执行)只是启动处理在模式inGroup
<强> II。 XSLT 1.0解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kComHeadGroup" match="com[head]"
use="generate-id(following-sibling::*[not(self::com[head])][1])"/>
<xsl:key name="kNonComHeadGroup" match="*[not(self::com/head)]"
use="generate-id(following-sibling::*[(self::com[head])][1])"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="/*/*[1]"/>
</root>
</xsl:template>
<xsl:template match=
"com[head
and
not(preceding-sibling::*[1]/self::com[head])
]">
<l>
<xsl:apply-templates mode="inGroup" select=
"key('kComHeadGroup',
generate-id
(following-sibling::*
[not(self::com[head])]
[1]
)
)"/>
</l>
<xsl:apply-templates select=
"following-sibling::*
[not(self::com[head])]
[1]
"/>
</xsl:template>
<xsl:template match="com[head]" mode="inGroup">
<li>
<lab><xsl:value-of select="head"/></lab>
<type><xsl:value-of select="body"/></type>
</li>
</xsl:template>
<xsl:template match="*[not(self::com/head)]">
<xsl:apply-templates mode="inGroup" select=
"key('kNonComHeadGroup',
generate-id(following-sibling::*[(self::com[head])][1])
)
"/>
<xsl:apply-templates select=
"following-sibling::com[head][1]"/>
</xsl:template>
<xsl:template match="*[not(self::com/head)]" mode="inGroup">
<p><xsl:value-of select="."/></p>
</xsl:template>
</xsl:stylesheet>
当应用于同一个XML文档(上图)时,再次生成相同的想要的正确结果:
<root>
<l>
<li>
<lab>A</lab>
<type>Type A</type>
</li>
<li>
<lab>B</lab>
<type>Type B</type>
</li>
<li>
<lab>C</lab>
<type>Type C</type>
</li>
<li>
<lab>D</lab>
<type>Type D</type>
</li>
</l>
<p>Type No</p>
<p>xml type X</p>
<p>xml type Y</p>
<l>
<li>
<lab>a</lab>
<type>Type a</type>
</li>
<li>
<lab>b</lab>
<type>Type b</type>
</li>
</l>
</root>
解释:与XSLT 2.0解决方案中的逻辑完全相同,但分组实现使用密钥。