我有以下XML:
<assessment>
<section>
<item>
<attributes>
<variables>
<variable>
<variable_name value="MORTIMER"/>
</variable>
</variables>
</attributes>
</item>
<item>
<attributes>
<variables>
<variable>
<variable_name value="FRED"/>
</variable>
</variables>
</attributes>
</item>
<item>
<attributes>
<variables>
<variable>
<variable_name value="MORTIMER"/>
</variable>
</variables>
</attributes>
</item>
</section>
</assessment>
我有以下XSLT来处理该XML:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kValueByVal" match="item//variables//variable_name"
use="@value"/>
<xsl:template match="assessment">
<xsl:for-each select="
.//item//variables//variable_name/@value
">
<xsl:value-of select=
"concat(., ' ', count(key('kValueByVal', .)), '
')"/>
<br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
它输出以下内容,这几乎是我想要的:
MORTIMER 2
FRED 1
MORTIMER 2
它列出了每个variable_names以及每个variable_names发生的次数。唯一的问题是,每次发生variable_name而不是只发生一次时,它会给这个计数一次。
这就是我想要输出的内容:
MORTIMER 2
FRED 1
如何修改XSLT代码以便为我提供?请注意,我们正在使用XSLT 1.0。
以下解决方案看起来应该可行,但不输出任何内容:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kValueByVal" match="item//variables//variable_name"
use="@value"/>
<xsl:template match="assessment">
<xsl:for-each select=".//item//variables//variable_name/@value[generate-id()
=
generate-id(key('kValueByVal',.)[1])]">
<xsl:value-of select=
"concat(., ' ', count(key('kValueByVal', .)), '
')"/>
<br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:2)
你真的需要了解Muenchian分组是如何工作的,否则你会永远地问相同问题的变体。
请阅读 Jeni Tennison's tutorial 。
以下是您最新问题的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kVarNameByVal" match="variable_name"
use="@value"/>
<xsl:template match=
"variable_name[generate-id()
=
generate-id(key('kVarNameByVal', @value)[1])
]
">
<xsl:value-of select=
"concat(@value, ' ', count(key('kVarNameByVal', @value)), '
')"/>
<br/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上执行此转换时,将生成所需的结果:
MORTIMER 2
FRED 1
答案 1 :(得分:1)
看到你正在使用XSLT 2.0,我会使用内置的grouping features。 (对于早期版本,您可能希望查看Muenchian分组。)
<?xml version="1.0" ?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kValueByVal" match="item//variables//variable_name"
use="@value"/>
<xsl:template match="assessment">
<xsl:for-each-group select=".//item//variables//variable_name" group-by="@value">
<xsl:value-of select="concat(current-grouping-key(), ' ', count(current-group()), '
')"/>
<br/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
你得到的是你要求的:
<xsl:for-each select=".//item//variables//variable_name/@value">
这意味着:对于这些属性中的每一个
分组时,您必须说:对于这些中的每一种
而且,你怎么知道这是独一无二的?用Muenchian方法:
<xsl:for-each select=".//item//variables//variable_name/@value[generate-id()
=
generate-id(key('kValueByVal',.)[1])]">
这意味着:那些是第一个拥有该密钥的人。
编辑:另外,当您知道输入架构时,请避免//
。
编辑:现在我可以看到你改变了密钥...那么,对于你的新密钥,谁是第一个?是! variable_name
元素:
<xsl:for-each select=".//item//variables//variable_name[generate-id()
=
generate-id(key('kValueByVal',@value)[1])]">
答案 3 :(得分:1)
这将在XSLT 1.0中完成。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kValueByVal" match="item//variables//variable_name"
use="@value"/>
<xsl:template match="assessment">
<xsl:for-each select="
//item//variables//variable_name[not(@value=ancestor::item/preceding-sibling::item//variables//variable_name/@value)]
">
<xsl:value-of select=
"concat(@value, ' ', count(key('kValueByVal', @value)), '
')"/>
<br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我得到的输出是
MORTIMER 2
<br />FRED 1
<br />
请注意,它假定了一些关于文档结构(祖先:: item位)的更多内容,但您应该可以从那里获取它。
答案 4 :(得分:0)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kValueByVal" match="item//variables//variable_name"
use="@value"/>
<xsl:template match="assessment">
<xsl:for-each
select="//item//variables//variable_name[
generate-id() =
generate-id(key('kValueByVal', @value)[1])]">
<xsl:value-of select=
"concat(./@value, ' ', count(key('kValueByVal', ./@value)), '
')"/>
<br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>