Xslt 如果一个数字重复,只显示一次
嗨,如果我有以下XML输入文件Xslt 如果一个数字重复,只显示一次,xslt,repeat,Xslt,Repeat,嗨,如果我有以下XML输入文件 <data> <group id= "1"> <phrase>Doc1</phrase> <document refid ="3"/> <document refid ="5"/> <document refid= "1"/> </group> <group id= "2"> <phrase>Doc2</phrase> <do
<data>
<group id= "1">
<phrase>Doc1</phrase>
<document refid ="3"/>
<document refid ="5"/>
<document refid= "1"/>
</group>
<group id= "2">
<phrase>Doc2</phrase>
<document refid ="2"/>
<document refid ="3"/>
<document refid= "6"/>
</group>
<group id= "3">
<phrase>Doc3</phrase>
<document refid ="2"/>
<document refid ="3"/>
<document refid= "4"/>
</group>
</data>
文件1
文档2
文件3
是否可以有一个输出来检查每个组,以查看文档“refid”编号是否未显示在以前的组中?例如,我希望我的输出为
<data>
<group id= "1">
<phrase>Doc1</phrase>
<document refid ="3"/>
<document refid ="5"/>
<document refid= "1"/>
</group>
<group id= "2">
<phrase>Doc2</phrase>
<document refid ="2"/>
<document refid= "6"/>
</group>
<group id= "3">
<phrase>Doc3</phrase>
<document refid= "4"/>
</group>
</data>
文件1
文档2
文件3
我试图在XSLT1.0中实现这一点。
我希望这能清楚地解释这个问题。我非常感谢你的帮助。
谢谢你这似乎很管用:
$cat style.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!--
This templates matches the document elements with a @refid that has already been used
in on of the previous groups. They are simply ignored.
-->
<xsl:template match="document[../preceding-sibling::group/document/@refid = current()/@refid]" />
<!--
Everything else gets copied to the output.
-->
<xsl:template match="@*|*|text()">
<xsl:copy>
<xsl:apply-templates select="@*|*|text()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0"?>
<data>
<group id="1">
<document refid="3"/>
<document refid="5"/>
<document refid="1"/>
</group>
<group id="2">
<document refid="2"/>
<document refid="6"/>
</group>
<group id="3">
<document refid="4"/>
</group>
</data>
编辑:要将其合并到样式表中,请尝试将第49行中每个的更改为:
<xsl:for-each select="document[not(../preceding-sibling::group/document/@refid = current()/@refid)]">
这里有一个简单有效的解决方案,使用键):
<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="kDocById" match="document" use="@refid"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="group">
<xsl:copy>
<xsl:apply-templates select=
"@*
|
node()[not(self::document)]
|
document
[generate-id()
=
generate-id(key('kDocById', @refid)[1])
]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<data>
<group id="1">
<phrase>Doc1</phrase>
<document refid="3"/>
<document refid="5"/>
<document refid="1"/>
</group>
<group id="2">
<phrase>Doc2</phrase>
<document refid="2"/>
<document refid="6"/>
</group>
<group id="3">
<phrase>Doc3</phrase>
<document refid="4"/>
</group>
</data>
在提供的XML文档上应用此转换时(反映OP在评论中的最新改进):
文件1
文档2
文件3
生成所需的正确结果:
<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="kDocById" match="document" use="@refid"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="group">
<xsl:copy>
<xsl:apply-templates select=
"@*
|
node()[not(self::document)]
|
document
[generate-id()
=
generate-id(key('kDocById', @refid)[1])
]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<data>
<group id="1">
<phrase>Doc1</phrase>
<document refid="3"/>
<document refid="5"/>
<document refid="1"/>
</group>
<group id="2">
<phrase>Doc2</phrase>
<document refid="2"/>
<document refid="6"/>
</group>
<group id="3">
<phrase>Doc3</phrase>
<document refid="4"/>
</group>
</data>
文件1
文档2
文件3
非常感谢您的帮助,但实际上我的XSLT文件中有最上面的代码,如果我尝试放置您为模板匹配提供的代码行,它会向我显示错误:元素必须仅在样式表的顶层使用。是否可以处理此错误?我不能从我的原始XSLT中删除它,因为我需要它来做其他事情。谢谢!有什么办法可以给你发邮件吗?它有点大,无法在我粘贴XSLT文件的注释部分正确显示它。我试着粘贴我的XML文件,但根本无法正常输出。我希望这有助于您理解我的问题您只是想让我添加到样式表的第49行?因为这不起作用:(你在回答中写的模板匹配如何。我是否需要处理它并将其粘贴到样式表中的某个位置?你可以使用我发布的作为独立样式表的整个样式表来预处理XML。但是如果你想将其合并到现有样式表中,那么你需要将第49行的
替换为标签。这是因为我的样式表中唯一重要的部分是XPath表达式。不要使用version=“1.1”
。这是XSLT的一个过时版本。请参阅。@mzjn哦,是的,我有1.0。很抱歉,这是一个打字错误。尽管将
放置在$total for each循环中是徒劳的。这只会使您更难提取值(迫使您使用node-set()扩展名),然后
元素会被丢弃,因为从$total使用的只是text()节点,而不是元素。即使使用node-set(),也需要节点集($total)/text()
,而不是节点集($total/text())
-只能将/text()
(子轴)应用于node-set()的结果,而不是结果树片段。我想提出一些积极的建议,但上面的输入XML与您发布的样式表所期望的输入太不匹配。例如,文档元素没有标题或@refid.Good question,+1。请参阅我的答案,以获得一个完整的解决方案,该解决方案简短、简单,并且是使用k的最有效的解决方案之一eys(明钦族分组)。天哪,非常感谢!!!这就成功了。我真的非常感谢你的时间和努力。非常感谢:)还有一个问题。如果我的输入更改为Doc1 Doc2格式,我如何让Doc1和Doc2也显示出来?您是否可以编辑发送给我的解决方案,以便我也可以打印Doc1和Doc2?谢谢!我真是感激不尽。太好了有你这样的优秀贡献者来帮助我们这些新手。非常感谢!:)@user807496:说“谢谢”的一种方式(这是SO的官方方式)就是接受最好的答案。为此,请单击答案旁边的复选标记。我很高兴我的回答有用。