更新 XSL 中的变量

发布于 2024-08-31 13:41:50 字数 1012 浏览 4 评论 0原文

XSL 有没有办法更新全局变量?

我想检查我已经转换了哪些元素并采取相应的行动。这将需要我以某种方式将元素的名称添加到某种列表中,并在每次转换新元素时更新它。

但由于 xsl:variable 不是人们所期望的“变量”,一旦定义了它,我就无法向它添加任何内容。

我有多个包含的数据文件,因此使用仅知道当前节点集的 xsl 函数将无济于事。

== 编辑==

这就是我的转变现在的样子。但它会包含每次在不同子文件中重复引用的文件。

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

    <xsl:output method="xml" />

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

    <!-- include the contents of referenced files -->
    <xsl:template match="reference">
        <xsl:apply-templates select="document(@url)/data/node()" />
    </xsl:template>

</xsl:transform>

数据文件看起来像这样:

<data>
    <reference url="another_data_file.xml"/>
    ... other stuff ...
</data>

Is there any way in XSL to update a global variable?

I want to check what elements i already transformed and act accordingly. That would require me to somehow add the names of the elements to some sort of list and update it each time a new element is transformed.

But since xsl:variable isn't "variable" in the sense one would expect, i have no way of adding anything to it once it has been defined.

I have multiple included data files, so using xsl functions that only know the current set of nodes will not help.

== Edit ==

This is what my transformation looks like now. But it will include files that are repeatedly referenced in different sub-files every time.

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

    <xsl:output method="xml" />

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

    <!-- include the contents of referenced files -->
    <xsl:template match="reference">
        <xsl:apply-templates select="document(@url)/data/node()" />
    </xsl:template>

</xsl:transform>

And the data files would look something like this:

<data>
    <reference url="another_data_file.xml"/>
    ... other stuff ...
</data>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无所的.畏惧 2024-09-07 13:41:50

XSLT 是一种函数式语言,不允许更新变量。如果您需要聚合多个步骤的结果,通常的方法是使用递归模板。例子:

<xsl:template name="transform-elements">
    <xsl:param name="elements-to-process" select="/.."/>
    <xsl:param name="processed-elements" select="/.."/>
    <xsl:if test="$elements-to-process">
        <xsl:variable name="element" select="$elements-to-process[1]"/>

        <!-- ... Do stuff with $element ...-->

        <!-- Recursively invoke template for remaining elements -->
        <xsl:call-template name="transform-elements">
            <xsl:with-param name="elements-to-process" 
                            select="$elements-to-process[position() != 1]"/>
            <xsl:with-param name="processed-elements" 
                            select="$processed-elements|$element"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

XSLT is a functional language, and does not allow variables to be updated. If you need to aggregate results over several steps, the usual approach is to use a recursive template. Example:

<xsl:template name="transform-elements">
    <xsl:param name="elements-to-process" select="/.."/>
    <xsl:param name="processed-elements" select="/.."/>
    <xsl:if test="$elements-to-process">
        <xsl:variable name="element" select="$elements-to-process[1]"/>

        <!-- ... Do stuff with $element ...-->

        <!-- Recursively invoke template for remaining elements -->
        <xsl:call-template name="transform-elements">
            <xsl:with-param name="elements-to-process" 
                            select="$elements-to-process[position() != 1]"/>
            <xsl:with-param name="processed-elements" 
                            select="$processed-elements|$element"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>
不离久伴 2024-09-07 13:41:50

遗憾的是,没有直接的方法,XSL 变量只能分配一次,但可以有条件地分配。

但是,块中定义的变量只能由该块及其子块访问,也许反转您的逻辑并迭代执行它会起作用?

这样,您就无法处理已经转换的内容,因为它已经完成了。

查看 xsl:Key 和 xsl:for-each 的用法,这将允许您对转换的节点进行排序。

引用 w3schools 的话,使用此 XML:

<persons>
  <person name="Tarzan" id="050676"/>
  <person name="Donald" id="070754"/>
  <person name="Dolly" id="231256"/>
</persons> 

和此 XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="preg" match="person" use="@id"/>

<xsl:template match="/">
  <html>
  <body>
  <xsl:for-each select="key('preg','050676')">
    <p>
    Id: <xsl:value-of select="@id"/><br />
    Name: <xsl:value-of select="@name"/>
    </p>
  </xsl:for-each>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet> 

将找到 ID 为“050676”的人。
也许使用这种具有更定义的键的方法会给您提供所需的结构?

Sadly, there isn't a direct way, XSL Variables are Assign Once only, but that can be assigned conditionally.

However, variables defined in a block are only accessible to that block and its children, perhaps inverting your logic and doing it iteratively would work instead ?

That way, you can't process stuff that's been transformed already, as it's already been completed.

Have a look into the usages of xsl:Key and xsl:for-each, this will let you order the nodes you transform.

To quote from w3schools, using this XML:

<persons>
  <person name="Tarzan" id="050676"/>
  <person name="Donald" id="070754"/>
  <person name="Dolly" id="231256"/>
</persons> 

And this XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="preg" match="person" use="@id"/>

<xsl:template match="/">
  <html>
  <body>
  <xsl:for-each select="key('preg','050676')">
    <p>
    Id: <xsl:value-of select="@id"/><br />
    Name: <xsl:value-of select="@name"/>
    </p>
  </xsl:for-each>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet> 

Will find the person with the ID of '050676'.
Perhaps using this method with more defined key would give you the structure you need?

还给你自由 2024-09-07 13:41:50

如果您的输入数据分布在多个文档中,那么将转换过程分为几个步骤可能是个好主意。

添加预处理转换,将输入文档中的相关部分提取到单个中间文档中。然后可以使用简单的 XSLT 转换该文档,您可能不会遇到当前面临的问题。

If your input data is spread over several documents it might be a good idea to split the transformation process into several steps.

Add a pre-processing transformation which pulls the relevant sections from the input documents into a single intermediate document. This document can then be transformed with a simple XSLT and you might not run into the problems which you are currently facing.

魂牵梦绕锁你心扉 2024-09-07 13:41:50

我不确定您尝试解析的文档的大小,但作为相对较小的 XML 文档的解决方案,您可以将结果输出到变量并应用扩展函数 node-set (来自 exslt 或 msxsl 等)对变量的内容应用转换,排除重复节点,就像处理单个 XML 文档一样。

I am not sure about the size of the documents you are trying to parse, but as a solution for relatively small XML documents you can output the result to a variable and having applied the extension function node-set (from exslt, or msxsl, etc.) apply transformation to the contents of the variable, excluding duplicate nodes as if you would process a single XML document.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文