我有这个InputXML
<Tokens>
<Element>ACNT=256265817; Expires=Wed, 15-Jul-2015 18:25:03 GMT; </Element>
<Element>SESSIONID=F4ED9CD79D212993DE8479F97F74FD41; Expires=Wed, 15-Jul-2015 18:25:03 GMT; </Element>
<Element>USER_ID=186900873; expires=Wed, 20-Jul-2008 06:25:03 GMT; </Element>
<Element>CONFIRM=a4d6f57259de6a2d5d78d0f74bddc19b; expires=Wed, 20-Jul-2008 06:25:03 GMT; </Element>
<Element>ID=186900873; expires=Wed, 20-Jul-2008 06:25:07 GMT; </Element>
<Element>CONFIRM=a4d6f57259de6a2d5d78d0f74bddc19b; expires=Wed, 20-Jul-2008 06:25:07 GMT; </Element>
<Element>SESSIONID=F4ED9CD79D212993DE8479F97F74FD41; Expires=Wed, 15-Jul-2015 18:25:03 GMT; </Element>
</Tokens>
每次具有最新到期时间的那个将始终处于下降状态。所以盲目地如何打印第二次重复的项目。请注意,当元素再次出现时,过期时间会发生变化。如果不重复打印第一个元素本身
输出为
<Tokens>
<Element>ACNT=256265817; Expires=Wed, 15-Jul-2015 18:25:03 GMT; </Element>
<Element>ID=186900873; expires=Wed, 20-Jul-2008 06:25:07 GMT; </Element>
<Element>CONFIRM=a4d6f57259de6a2d5d78d0f74bddc19b; expires=Wed, 20-Jul-2008 06:25:07 GMT; </Element>
<Element>SESSIONID=F4ED9CD79D212993DE8479F97F74FD41; Expires=Wed, 15-Jul-2015 18:25:03 GMT; </Element>
</Tokens>
如何以通用方式仅提供第二个元素,而不查看通过 xslt 1.0 的元素值。由于内部可能有以不同键开头的值(ID/CONFIRM/SESSIONID/ACNT/GTID 等(
我尝试了set:distinct-values,但它实际上与整个文本相匹配。 在这种情况下,由于到期时间,不会有任何
在样式表模板中设置不同的代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:set="http://exslt.org/sets">
<xsl:template match="/">
<Tokens>
<xsl:for-each select="set:distinct(/Tokens/Element)">
<Element><xsl:copy-of select="."/></Element>
</xsl:for-each>
</Tokens>
</xsl:template>
</xsl:stylesheet>
不能对部分值使用set:distinct()
。改用 Muenchian 分组(有一个小的变化来获取每个组的最后一个节点而不是第一个节点(:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="elem-by-val" match="Element" use="substring-before(., ';')" />
<xsl:template match="/Tokens">
<Tokens>
<xsl:copy-of select="Element[count(. | key('elem-by-val', substring-before(., ';'))[last()]) = 1]"/>
</Tokens>
</xsl:template>
</xsl:stylesheet>
请注意,应用于您的示例输入,结果:
<?xml version="1.0" encoding="UTF-8"?>
<Tokens>
<Element>ACNT=256265817; Expires=Wed, 15-Jul-2015 18:25:03 GMT; </Element>
<Element>USER_ID=186900873; expires=Wed, 20-Jul-2008 06:25:03 GMT; </Element>
<Element>ID=186900873; expires=Wed, 20-Jul-2008 06:25:07 GMT; </Element>
<Element>CONFIRM=a4d6f57259de6a2d5d78d0f74bddc19b; expires=Wed, 20-Jul-2008 06:25:07 GMT; </Element>
<Element>SESSIONID=F4ED9CD79D212993DE8479F97F74FD41; Expires=Wed, 15-Jul-2015 18:25:03 GMT; </Element>
</Tokens>
与你的不同,因为USER_ID
和ID
不一样.如果要忽略标签而仅查看值(这很危险,因为 ACNT 和 USER_ID 可能只是巧合而相同(,则可以使用
substring-before(substring-after(., '='), ';')
而不是:
substring-before(., ';')
这是一种可能的方法:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Tokens/Element">
<xsl:if test="not(following-sibling::Element[substring-before(.,';')=substring-before(current(),';')])">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
<xsl:template match="@* | node()">...
:标识模板。将此模板应用到的节点和属性复制到输出 XML,保持不变。<xsl:template match="Tokens/Element">...
:覆盖作为Tokens
的直接子节点的Element
节点的身份模板。重复的Element
节点部分由第一个;
字符之前的内部文本确定 - 使用substring-before()
函数。 仅当输出 XML 没有具有相同substring-before()
值的下一个同级时,Element
才将其复制到输出 XML,换句话说,对于每个不同的substring-before()
值,仅复制最后出现的元素。