我有这样的XML:
<?xml version="1.0" encoding="UTF-8"?>
<Section>
<Chapter>
<Cell colname="1">
<Value>A</Value>
</Cell>
<Cell colname="2">
<MyValue>AAA</MyValue>
<MyValue>BBB</MyValue>
</Cell>
<Cell colname="3">
<MyCar>Honda</MyCar>
</Cell>
</Chapter>
<Chapter>
<Cell colname="1">
<Value>C</Value>
</Cell>
<Cell colname="2">
<MyValue>CCC</MyValue>
</Cell>
<Cell colname="3">
<MyCar>Toyota</MyCar>
</Cell>
</Chapter>
</Section>
我喜欢有一条消息(稍后转换它们的标签)输出如下:
一个 AAA 本田 一个 BBB 本田 C CCC 丰田
这是我的XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="Section//Chapter"/>
</xsl:template>
<xsl:template match="Chapter">
<xsl:for-each select="Cell[@colname='2']//MyValue">
<xsl:message>
<xsl:value-of select="Cell[@colname='1']/Value"/>
<xsl:value-of select="."/>
<xsl:value-of select="Cell[@colname='3']/MyCar"/>
</xsl:message>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
不幸的是,它没有输出我想要它做的事情:(。
我意识到for-each会改变上下文,所以剩下的值不会做任何事情。
对此有什么解决方法?
TIA,
约翰
答案 0 :(得分:3)
这个XSLT 2.0转换(等效的XSLT 1.0转换可以用这个机制编写)。
请注意:这是一个适用于任意数量子级的通用解决方案,不依赖于硬编码名称。
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Chapter">
<xsl:apply-templates select="Cell[1]"/>
</xsl:template>
<xsl:template match="Cell">
<xsl:param name="pText" as="xs:string*"/>
<xsl:apply-templates select="*[1]">
<xsl:with-param name="pText" select="$pText"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Cell/*">
<xsl:param name="pText" as="xs:string*"/>
<xsl:variable name="vText" as="xs:string*"
select="$pText, string(.)"/>
<xsl:sequence select=
"$vText
[not(current()/../following-sibling::Cell)]"/>
<xsl:apply-templates select="../following-sibling::Cell[1]">
<xsl:with-param name="pText" select="$vText"/>
</xsl:apply-templates>
<xsl:apply-templates select="following-sibling::*">
<xsl:with-param name="pText" select="$pText"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<Section>
<Chapter>
<Cell colname="1">
<Value>A</Value>
</Cell>
<Cell colname="2">
<MyValue>AAA</MyValue>
<MyValue>BBB</MyValue>
</Cell>
<Cell colname="3">
<MyCar>Honda</MyCar>
</Cell>
</Chapter>
<Chapter>
<Cell colname="1">
<Value>C</Value>
</Cell>
<Cell colname="2">
<MyValue>CCC</MyValue>
</Cell>
<Cell colname="3">
<MyCar>Toyota</MyCar>
</Cell>
</Chapter>
</Section>
产生完全正确的结果:
A AAA Honda A BBB Honda C CCC Toyota
<强>解释强>:
这基本上是一个任务,用于生成属于N个组的所有值组合(Cell
的子组成一个组),从每个组中获取一个项目。
在K组的任何项目中,我们将此项目添加到组1,2,...,K-1的当前项目组合中。然后我们将这个新形成的组合传递给K + 1组。如果我们是最后一组(N)中的项目,我们会打印出(xsl:sequence
)整个累积组合。
当控件返回时,其余组(K + 1,K + 2,...,N)的所有元素组合都已附加到组1,2的组项目的当前组合中,...,K。所有这些组合已经打印出来。
我们传递了传递给我们的相同组元素组合 - 现在我们将它传递给当前组中的以下项目(以下兄弟)。
答案 1 :(得分:1)
我稍微修改了你的方法,因为我猜你真的不想使用<xsl:message>
诊断操作。除此之外,我没有在输出上生成XML而且我没有使用for-each:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text" version="1.0" encoding="iso-8859-1" indent="yes"/>
<xsl:template match="/Section">
<xsl:apply-templates select="Chapter"/>
</xsl:template>
<xsl:template match="Chapter">
<xsl:apply-templates select="Cell/MyValue" />
</xsl:template>
<xsl:template match="MyValue">
<xsl:value-of select="../../Cell[@colname='1']/Value/text()"/>
<xsl:text> </xsl:text>
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
<xsl:value-of select="../../Cell[@colname='3']/MyCar"/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>