如果重复或仅第一个xslt,则仅打印第二个时间节点

时间:2015-07-19 06:39:25

标签: xml xslt xslt-1.0

我有这个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查看元素值的情况下,以通用方式仅提供第二个元素。作为Inside,可能有以不同键开头的值(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>

2 个答案:

答案 0 :(得分:2)

您不能对部分值使用set:distinct()。请改用Muenchian grouping(使用较小的变体来获取每个组的最后一个节点而不是第一个节点):

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_IDID不同。如果你想忽略标签并只查看值(这是危险的,因为ACNT和USER_ID可能只是巧合相同),你可以使用

substring-before(substring-after(., '='), ';')

而不是:

substring-before(., ';')

答案 1 :(得分:1)

这是一种可能的方式:

<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">...:覆盖Element的直接子节点Tokens节点的身份模板。在第一个Element字符使用;函数之前,由内部文本部分确定的重复substring-before()节点。 Element仅复制到输出XML ,如果它没有相同substring-before()的下一个兄弟,换句话说,对于每个不同的substring-before()值,仅最后一次出现的元素被复制。