我目前停留在获取一组价值<NAME>
为关键字的不同值。
我有以下示例XML:
<SAMPLE>
<FIRST>
<SUBSET>
<DATA>
<NAME>DataName1</NAME>
</DATA>
<FILE>
<NAME>DataName5</NAME>
</FILE>
</SUBSET>
</FIRST>
<SECOND>
<DATA>
<NAME>DataName1</NAME>
</DATA>
<FILE>
<NAME>DataName2</NAME>
</FILE>
<DATA>
<NAME>DataName3</NAME>
</DATA>
</SECOND>
<THIRD>
<DATA>
<NAME>DataName1</NAME>
</DATA>
<FILE>
<NAME>DataName4</NAME>
</FILE>
</THIRD>
</SAMPLE>
我想要实现的目标是从DATA和File Tags中获取NAME值,结果如下:
<SAMPLE>
<NAME>DataName1</NAME>
<NAME>DataName2</NAME>
<NAME>DataName3</NAME>
<NAME>DataName4</NAME>
<NAME>DataName5</NAME>
</SAMPLE>
以下是我使用[(NAME=preceding::NAME)]
的代码,但它无效..
<xsl:template name="Sample">
<SAMPLE>
<xsl:for-each select="((($srcFile/SAMPLE/FIRST/SUBSET)|($srcFile/SAMPLE/SECOND)|($srcFile/SAMPLE/THIRD))/(DATA | FILE))[(NAME=preceding::NAME)]">
<xsl:for-each select="NAME"><xsl:element name="{name(.)}"><xsl:value-of select="."/></xsl:element></xsl:for-each>
</xsl:for-each>
</SAMPLE>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="Sample"/>
</xsl:template>
不幸的是,for-each部分中的上述代码仅返回以下内容:
<SAMPLE>
<NAME>DataName1</NAME>
<NAME>DataName1</NAME>
</SAMPLE>
不幸的是,取出[(NAME=preceding::NAME)]
将返回所有重复的结果..我认为我在正确的位置有过滤器代码,因为我甚至在使用此过滤器之前添加了整体()[]
提前感谢所有帮助/建议!
答案 0 :(得分:1)
在XSLT 2.0中,这非常简单:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<SAMPLE>
<xsl:for-each select="distinct-values(//NAME)">
<NAME>
<xsl:value-of select="." />
</NAME>
</xsl:for-each>
</SAMPLE>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
一个简单的XSLT-1.0解决方案是排除重复项并按其词法顺序对它们进行排序。生成xsl:key
个所有NAME
个节点,并将此列表再次与所有NAME
个节点进行比较:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" />
<xsl:key name="names" match="NAME" use="text()" />
<xsl:template match="/SAMPLE">
<SAMPLE>
<xsl:for-each select="//NAME[generate-id() = generate-id(key('names',text()))]">
<xsl:sort select="." order="ascending" />
<NAME><xsl:value-of select="." /></NAME>
</xsl:for-each>
</SAMPLE>
</xsl:template>
</xsl:stylesheet>
输出结果为:
<?xml version="1.0"?>
<SAMPLE>
<NAME>DataName1</NAME>
<NAME>DataName2</NAME>
<NAME>DataName3</NAME>
<NAME>DataName4</NAME>
<NAME>DataName5</NAME>
</SAMPLE>
答案 2 :(得分: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:variable name="vDoc" select="document('file:///C:/temp/delete/sample.xml')"/>
<xsl:template match="/*">
<xsl:for-each-group select="$vDoc/*/SECOND/SET" group-by="NAME">
<xsl:sequence select="."/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
此转换应用于任何源XML文档(未使用)和文件C:\temp\delete\sample.xml
(注意我已更改SAMPLE\FIRST\SET\NAME
的值以显示它未复制到结果树) :
<SAMPLE>
<FIRST>
<SET>
<NAME>manX</NAME>
<STRING1>what</STRING1>
<STRING2>today</STRING2>
</SET>
</FIRST>
<SECOND>
<SET>
<NAME>man1</NAME>
<STRING1>what</STRING1>
<STRING2>today</STRING2>
</SET>
<SET>
<NAME>man1</NAME>
<STRING1>what</STRING1>
<STRING2>today</STRING2>
</SET>
<SET>
<NAME>man2</NAME>
<STRING1>how</STRING1>
<STRING2>tomorrow</STRING2>
</SET>
<SET>
<NAME>man3</NAME>
<STRING1>hello</STRING1>
<STRING2>yesterday</STRING2>
</SET>
</SECOND>
</SAMPLE>
产生了想要的正确结果:
<SET>
<NAME>man1</NAME>
<STRING1>what</STRING1>
<STRING2>today</STRING2>
</SET>
<SET>
<NAME>man2</NAME>
<STRING1>how</STRING1>
<STRING2>tomorrow</STRING2>
</SET>
<SET>
<NAME>man3</NAME>
<STRING1>hello</STRING1>
<STRING2>yesterday</STRING2>
</SET>
<强> 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:variable name="vDoc" select="document('file:///C:/temp/delete/sample.xml')"/>
<xsl:key name="kSecondSetsByName" match="SECOND/SET" use="NAME"/>
<xsl:template match="/">
<xsl:apply-templates select="$vDoc/*/SECOND"/>
</xsl:template>
<xsl:template match="SET[generate-id()=generate-id(key('kSecondSetsByName', NAME)[1])]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
<强>解释强>:
使用标准XSLT 2.0指令<xsl:for-each-group>
,其属性为group-by
。
在XSLT 1.0解决方案中使用 Muenchian method for grouping