我必须在< xsl:for-each>的上下文中仅选择
XML文档中的唯一记录.环.我被Visual Studio限制为使用XSL 1.0.
<availList> <item> <schDate>2010-06-24</schDate> <schFrmTime>10:00:00</schFrmTime> <schToTime>13:00:00</schToTime> <varIoUsOtherElements></varIoUsOtherElements> </item> <item> <schDate>2010-06-24</schDate> <schFrmTime>10:00:00</schFrmTime> <schToTime>13:00:00</schToTime> <varIoUsOtherElements></varIoUsOtherElements> </item> <item> <schDate>2010-06-25</schDate> <schFrmTime>10:00:00</schFrmTime> <schToTime>12:00:00</schToTime> <varIoUsOtherElements></varIoUsOtherElements> </item> <item> <schDate>2010-06-26</schDate> <schFrmTime>13:00:00</schFrmTime> <schToTime>14:00:00</schToTime> <varIoUsOtherElements></varIoUsOtherElements> </item> <item> <schDate>2010-06-26</schDate> <schFrmTime>10:00:00</schFrmTime> <schToTime>12:00:00</schToTime> <varIoUsOtherElements></varIoUsOtherElements> </item> </availList>
唯一性必须基于三个子元素的值:schDate,schFrmTime和schToTime.如果两个项元素对于所有三个子元素具有相同的值,则它们是重复的.在上面的XML中,第一项和第二项是重复的.其余的都是独特的.如上所述,每个项目包含我们不希望包括在比较中的其他元素. “独特性”应该是这三个要素的一个因素,而仅仅是那些要素.
我试图通过以下方式实现这一目标:
availList/item[not(schDate = preceding:: schDate and schFrmTime = preceding:: schFrmTime and schToTime = preceding:: schToTime)]
这背后的想法是选择没有先前元素的记录,其中schDate,schFrmTime和schToTime相同.但是,它的输出缺少最后一项.这是因为我的XPath实际上排除了所有子元素值在整个前一个文档中匹配的项目.没有单个项目匹配所有最后一个项目的子元素 – 但由于每个元素的值单独存在于另一个项目中,因此最后一个项目将被排除.
通过将所有子值作为连接字符串与每个前面项的相同连接值进行比较,我可以得到正确的结果.有人知道我能做到这一点吗?
解决方法
I.作为单个XPath表达式:
/*/item[normalize-space() and not(. = preceding-sibling::item)]
II.使用密钥更高效(XSLT)实现:
<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="kItemByVal" match="item" use="."/> <xsl:template match="/"> <xsl:copy-of select= "*/item[generate-id() = generate-id(key('kItemByVal',.))] "/> </xsl:template> </xsl:stylesheet>
I和II都应用于提供的XML文档时,正确选择/复制以下节点:
<item><schDate>2010-06-24</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>13:00:00</schToTime></item> <item><schDate>2010-06-25</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>12:00:00</schToTime></item> <item><schDate>2010-06-26</schDate><schFrmTime>13:00:00</schFrmTime><schToTime>14:00:00</schToTime></item> <item><schDate>2010-06-26</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>12:00:00</schToTime></item>
更新:如果< item>有其他孩子,然后这个转变:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:key name="kItemBy3Children" match="item" use="concat(schDate,'+',schFrmTime,schToTime)"/> <xsl:template match="/"> <xsl:copy-of select= "*/item[generate-id() = generate-id(key('kItemBy3Children',concat(schDate,schToTime) ) ) ] "/> </xsl:template> </xsl:stylesheet>
产生想要的结果.