XSLT不对多个模板匹配进行排序

时间:2018-01-31 04:51:01

标签: xml xslt xslt-1.0

XSLT 1.0

我正在对文本消息输出进行排序,并尝试按日期列出短信和短信。 数据被结构化为:

  <smses>
    <sms address="555555001" date="1517372455000" readable_date="Jan 30, 2018" message="Hello" name="John" />
    <sms address="555555001" date="1517372455004" readable_date="Jan 30, 2018" message="Hello" name="John" />
    <sms address="555555009" date="1517372458000" readable_date="Jan 30, 2018" message="Hello" name="Jane" />
    <sms address="555555009" date="1517372458001" readable_date="Jan 30, 2018" message="Hello" name="Jane" />
    <sms address="555555009" date="1517372458002" readable_date="Jan 30, 2018" message="Hello" name="Jane" />
    <sms address="555555001" date="1517372455005" readable_date="Jan 30, 2018" message="Hello" name="John" />
    <mms address="555555001" date="1517372455001" readable_date="Jan 30, 2018" message="Hello" name="John" />
    <mms address="555555001" date="1517372455002" readable_date="Jan 30, 2018" message="Hello" name="John" />
    <mms address="555555001" date="1517372455003" readable_date="Jan 30, 2018" message="Hello" name="John" />
   </smses>

我正在生成一个按“John”过滤的键(@readable_date存在于实际数据中)

<xsl:key name="shortDate" match="sms[@name='John']|mms[@name='John']" use="@readable_date" />

<xsl:template match="/">    
    <xsl:apply-templates select="/smses/sms[generate-id(.)=generate-id(key('shortDate',@readable_date)[1])] | /smses/mms[generate-id(.)=generate-id(key('shortDate',@readable_date)[1])]">
      <xsl:sort select="@date" data-type="number" />
    </xsl:apply-templates>  
</xsl:template>

<xsl:template match="sms|mms">
        <xsl:for-each select="key('shortDate',@readable_date)">
            <xsl:value-of select="@name" /><xsl:value-of select="@readable_date" /><xsl:value-of select="@message" />
        </xsl:for-each>
</xsl:template> 

无论我尝试什么,mms消息总是在sms消息之后,而不是所有节点按日期排序。

2 个答案:

答案 0 :(得分:1)

如果您只查找发送到<xsl:key>的邮件,我认为您无需定义John。您可以在<xsl:for-each>上应用John过滤,然后在@date上应用排序。下面是XSLT模板。

<xsl:template match="smses">
    <xsl:for-each select="*[@name='John']">
        <xsl:sort select="@date" order="ascending" data-type="number" />
        <output>
            <xsl:value-of select="@message" />
        </output>
    </xsl:for-each>
</xsl:template>

为了验证输出,我对@message值进行了一些更改以了解其中的差异。以下是更新的输入XML。

<smses>
    <sms address="555555001" date="1517372455000" readable_date="Jan 30, 2018" message="Hello, This is SMS 1 for John." name="John" />
    <sms address="555555001" date="1517372455004" readable_date="Jan 30, 2018" message="Hello, This is SMS 2 for John." name="John" />
    <sms address="555555009" date="1517372458000" readable_date="Jan 30, 2018" message="Hello, This is SMS 1 for Jane." name="Jane" />
    <sms address="555555009" date="1517372458001" readable_date="Jan 30, 2018" message="Hello, This is SMS 2 for Jane." name="Jane" />
    <sms address="555555009" date="1517372458002" readable_date="Jan 30, 2018" message="Hello, This is SMS 3 for Jane." name="Jane" />
    <sms address="555555001" date="1517372455005" readable_date="Jan 30, 2018" message="Hello, This is SMS 3 for John." name="John" />
    <mms address="555555001" date="1517372455001" readable_date="Jan 30, 2018" message="Hello, This is MMS 1 for John." name="John" />
    <mms address="555555001" date="1517372455002" readable_date="Jan 30, 2018" message="Hello, This is MMS 2 for John." name="John" />
    <mms address="555555001" date="1517372455003" readable_date="Jan 30, 2018" message="Hello, This is MMS 3 for John." name="John" />
</smses>

使用上述XML,当应用XSLT模板时,将生成以下排序的输出

<output>Hello, This is SMS 1 for John.</output>
<output>Hello, This is MMS 1 for John.</output>
<output>Hello, This is MMS 2 for John.</output>
<output>Hello, This is MMS 3 for John.</output>
<output>Hello, This is SMS 2 for John.</output>
<output>Hello, This is SMS 3 for John.</output>

答案 1 :(得分:1)

您按@readable_date分组元素,并对组进行排序;然后输出每个组的内容而不进一步排序(即,每个组按文档顺序输出)。

但是在您的示例数据中,所有元素都具有相同的@readable_date,因此只有一个组,因此对组进行排序无效。您需要对组中的项目进行排序,即xsl:for-each模板规则中的match="sms|mms"指令需要xsl:sort规范。