【问题标题】:XSLT: filter/group nodes in variablesXSLT:过滤/分组变量中的节点
【发布时间】:2017-05-15 16:55:08
【问题描述】:

我正在尝试过滤/分组变量中的节点。

XML:

<?xml version="1.0" encoding="UTF-8"?>
<row>
    <cell n="1"/>
    <cell n="2"/>
    <cell n="3"/>
    <cell n="4"/>
    <cell n="2"/>
    <cell n="5"/>
</row>

XSLT 2:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="row">
        <xsl:element name="row">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>   

    <xsl:template match="cell">
        <xsl:variable name="attribute" select="@n"/>
        <xsl:variable name="sequence">
            <xsl:call-template name="seq">
                <xsl:with-param name="attribute" select="$attribute"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:for-each-group select="$sequence" group-by="cell/@val">
            <xsl:sequence select="."></xsl:sequence>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template name="seq">
        <xsl:param name="attribute"/>
        <xsl:element name="cell">
            <xsl:attribute name="val">
                <xsl:value-of select="$attribute"/>
            </xsl:attribute>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<row>
    <cell val="1"/>
    <cell val="2"/>
    <cell val="3"/>
    <cell val="4"/>
    <cell val="5"/>
</row>

XML 代码只是一个复杂得多的文件的示例。我想要做的是首先处理所有元素cell 并将结果保存在一个变量中。在第二次运行中,我想过滤或重新组合序列的节点。

我还尝试使用谓词过滤$sequence

<xsl:sequence select="$sequence/*[@val != preceding-sibling::cell/@val]"/> 

在这种情况下,输出文件为空。

编辑 2(现在可以使用):

<?xml version="1.0" encoding="UTF-8"?>

<xsl:template match="row">
    <xsl:variable name="sequence">
        <xsl:for-each select="cell">
            <xsl:variable name="attribute" select="@n"/>
            <xsl:call-template name="seq">
                <xsl:with-param name="attribute" select="$attribute"/>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:variable>
    <row>
        <xsl:for-each-group group-by="@val" select="$sequence/*">
            <xsl:sequence select="."/>
        </xsl:for-each-group>
    </row>
</xsl:template>

<xsl:template name="seq">
    <xsl:param name="attribute"/>
    <xsl:element name="cell">
        <xsl:attribute name="val">
            <xsl:value-of select="$attribute"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>

【问题讨论】:

  • 你的例子根本不清楚。如果要首先处理所有cell 元素并将结果存储在变量中以供进一步处理,则必须从row(或更高版本)的上下文中执行此操作。我想这就是目前可以说的所有内容。
  • 我试图编辑早期的代码,但现在我无法通过$attribute。恐怕我对 XSLT 的了解在这里遇到了局限。
  • 同上迈克尔的评论——不清楚你想做什么。我还要补充一点,您的$sequence 变量将只包含一个cell 元素,实际上是cell 元素的副本,它是&lt;xsl:template match="cell"&gt; 中匹配的上下文。由于$sequence 只有一个元素,您尝试使用preceding-sibling 过滤$sequence 失败。正如迈克尔所说,要一次定位多个cell,您需要从row 或更高级别的上下文开始。
  • 你需要首先解释你到底想在这里完成什么。以及为什么需要分两步完成。
  • 基本上我想过滤一个保存在变量中的序列。我知道,有更简单的方法可以实现所需的输出。我试图举一个例子来说明这个问题。 Step1:调用模板并将结果保存在变量中。第 2 步:过滤第 1 步的结果。

标签: variables xslt xslt-2.0 xslt-grouping


【解决方案1】:

这是一个 XSLT 2.0 样式表,它首先将 &lt;cell n="x"&gt;...&lt;/cell&gt; 转换为 &lt;cell val="n"&gt;...&lt;/cell&gt;,然后通过 val 属性对这些单元格元素进行分组以消除重复:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="row">
        <xsl:copy>
            <xsl:variable name="transformed-cells">
                <xsl:apply-templates select="cell"/>
            </xsl:variable>
            <xsl:for-each-group select="$transformed-cells/cell" group-by="@val">
                <xsl:copy-of select="."/>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="cell/@n">
        <xsl:attribute name="val" select="."/>
    </xsl:template>

</xsl:transform>

输出是

<row>
   <cell val="1"/>
   <cell val="2"/>
   <cell val="3"/>
   <cell val="4"/>
   <cell val="5"/>
</row>

http://xsltransform.net/a9Giwz

【讨论】:

  • 谢谢!恐怕我的例子不是那么好。它不是关于预期的输出,而是关于使用一个变量来实现输出,该变量保存了调用模板的结果
  • 好吧,无论您在xsl:variable 内部使用xsl:call-template(因为我不明白的原因您似乎想要这样做)还是xsl:apply-templates(正如我在示例中所做的那样因为这是 XSLT 中处理节点的常用方法)不会改变我的答案中显示的xsl:for-each-group 中变量的使用。所以这个答案应该有助于展示如何处理变量的内容。
  • 我想要xsl:call-template,因为我引用的样式表使用了它。无论如何,你是对的。我以错误的方式使用了xsl:for-each-group。现在一切正常。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-03
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
相关资源
最近更新 更多