尝试使用变量元素名称打印 XSLT 中的节点值

发布于 2024-12-14 16:22:45 字数 1415 浏览 5 评论 0原文

那么这几天有一个问题一直困扰着我。它应该相当容易,但 XSLT 调试起来实在是太痛苦了。我们在 java 1.6

输入 XML

<?xml version="1.0" encoding="UTF-8"?>
<rfb2>
    <rfb2_item>
        <VALDATE>2011-10-23</VALDATE>
        <FUND_ID>300</FUND_ID>
        <SEC_ID>34567</SEC_ID>
    </rfb2_item>
    <rfb2_item>
        <VALDATE>2011-1-09</VALDATE>
        <FUND_ID>700</FUND_ID>
        <SEC_ID>13587</SEC_ID>
    </rfb2_item>
    <rfb2_item>
        <VALDATE>2011-3-09</VALDATE>
        <FUND_ID>200</FUND_ID>
        <SEC_ID>999334</SEC_ID>
    </rfb2_item>
<rfb2>

上使用 Xalan 1.0我们需要将 XML 转换为每个 rfb2_item 的逗号分隔值列表,因此样式表始终迭代 rfb2_item 节点。我们在样式表中使用一个参数来控制将输出 rfb2_item (valdate,fund_id,sec_id) 的哪些元素以及按什么顺序输出,例如

<xsl:param name="$outputElements" select="'VALDATE,FUND_ID'"/>
..outputs...

2011-10-23,300
2011-1-09,700
2011-3-09,200



<xsl:param name="$outputElements" select="'SEC_ID'"/>    
..outputs...

34567
13587
999334

特殊情况,如果 $outputElements 为 '*',则仅输出中的元素它们在输入 xml 中出现的顺序

<xsl:param name="$outputElements" select="'*'"/>

..outputs...

2011-10-23,300,34567
2011-1-09,700,13587
2011-3-09,200,999334

那么,我的问题是我们如何编写一个模板来基于 $outputElements 参数创建所需的输出?一个有效的例子会很棒......

So here's a problem that's been bugging me for the last few days. It should be fairly easy, but XSLT is just such a pain to debug. We're using Xalan 1.0 on java 1.6

Input XML

<?xml version="1.0" encoding="UTF-8"?>
<rfb2>
    <rfb2_item>
        <VALDATE>2011-10-23</VALDATE>
        <FUND_ID>300</FUND_ID>
        <SEC_ID>34567</SEC_ID>
    </rfb2_item>
    <rfb2_item>
        <VALDATE>2011-1-09</VALDATE>
        <FUND_ID>700</FUND_ID>
        <SEC_ID>13587</SEC_ID>
    </rfb2_item>
    <rfb2_item>
        <VALDATE>2011-3-09</VALDATE>
        <FUND_ID>200</FUND_ID>
        <SEC_ID>999334</SEC_ID>
    </rfb2_item>
<rfb2>

We need to transform the XML into a comma-separated list of values for each rfb2_item, so the style sheet always iterates the rfb2_item nodes. We are using a parameter in the style sheet to control which elements of rfb2_item (valdate,fund_id,sec_id) that will be output, and in what order, for example

<xsl:param name="$outputElements" select="'VALDATE,FUND_ID'"/>
..outputs...

2011-10-23,300
2011-1-09,700
2011-3-09,200



<xsl:param name="$outputElements" select="'SEC_ID'"/>    
..outputs...

34567
13587
999334

Special case where if $outputElements is '*', just output the elements in the order they appear in the input xml

<xsl:param name="$outputElements" select="'*'"/>

..outputs...

2011-10-23,300,34567
2011-1-09,700,13587
2011-3-09,200,999334

So, my question is how do we write a template to create the desired output based on the $outputElements parameter? A working example would be great...

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

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

发布评论

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

评论(2

云淡月浅 2024-12-21 16:22:48

是的,FailedDev 是对的。有人会为你写:

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

    <xsl:output method="text" />

    <xsl:param name="outputElements" select=" 'FUND_ID,SEC_ID,VALDATE' " />

    <xsl:template match="rfb2_item">

        <xsl:for-each select="*[contains($outputElements, local-name()) or $outputElements = '*']">
            <xsl:sort select="string-length(substring-before($outputElements, local-name(.)))" />
            <xsl:value-of select="text()" />
            <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>
</xsl:text>

    </xsl:template>

</xsl:stylesheet>

一点解释。 xsl:for-each 将选择当前 rfb2_item 中的每个元素,其本地名称包含在 outputElements 参数中,或者其中 outputElements 参数是 * (如果是这种情况,则始终会产生 true)。然后,它会根据 outputElements 中本地名称之前的子字符串的长度对这些内容进行排序。由于当该名称稍后出现在该参数中时该值会变得更高,因此这会导致根据您的参数进行排序。

示例:元素 VALDATE 将为 substring-before 函数生成 FUND_ID,SEC_ID,而该函数又会生成 14 作为字符串长度。该值高于 SEC_ID 获得的 8,这意味着 VALDATE 值排在 SEC_ID 之后。

xsl:sort 之后,我们只需使用 xsl:value-of 来输出元素值。您可能想修剪那里无关的空白。最后,我们测试该位置是否不等于当前上下文中最后一个节点的位置(即 xsl:for-each after 排序后的位置),并且如果是,则输出一个逗号。这可以避免在最后一个值之后输出逗号。

我使用 xsl:text 插入的换行符采用 Windows/DOS 约定。如果文件应该只使用换行符来换行,而不是回车+换行,请删除

请注意,这不会转义 CSV 输出中的逗号!我把这个留给你。考虑使用 扩展函数 将此任务委托给 Java 可能会很有趣,如果事实证明,在 XSLT/XPath 中这太困难了。

Yup, FailedDev is right. Someone would write it for you:

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

    <xsl:output method="text" />

    <xsl:param name="outputElements" select=" 'FUND_ID,SEC_ID,VALDATE' " />

    <xsl:template match="rfb2_item">

        <xsl:for-each select="*[contains($outputElements, local-name()) or $outputElements = '*']">
            <xsl:sort select="string-length(substring-before($outputElements, local-name(.)))" />
            <xsl:value-of select="text()" />
            <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>
</xsl:text>

    </xsl:template>

</xsl:stylesheet>

Bit of explanation. The xsl:for-each is gonna select each element in the current rfb2_item for which the local name is contained in the outputElements parameter, or for which the outputElements parameter is * (which would always yield true if that's the case). It's then gonna sort those based on the length of the substring that goes before that local name in outputElements. Since this value becomes higher when the name occurs later in that parameter, this results in ordering based on your parameter.

Example: element VALDATE would yield FUND_ID,SEC_ID for the substring-before function, which in turn would yield 14 as string length. This is higher than the 8 that you'd get for SEC_ID, meaning the VALDATE value is ordered after SEC_ID.

After the xsl:sort, we're simply using xsl:value-of to output the element value. You might want to trim extraneous whitespace there. Finally, we're testing if the position is not equal to that of the last node in the current context (which is that of xsl:for-each after sorting) and if so, output a comma. This avoids outputting a comma after the last value.

The line break I've inserted using xsl:text assumes the Windows/DOS convention. Remove the if the file should only use new line characters for line breaks, instead of carriage return + new line.

Note that this does not escape commas in your CSV output! I'll leave that up to you. It could be interesting to look into using extension functions for delegating this task to Java if it proves too difficult in XSLT/XPath.

追风人 2024-12-21 16:22:48

有时在这种情况下,值得考虑使用 XSLT 生成或修改 XSLT 代码的可能性。您可以通过这种方式进一步进行参数化 - 例如控制输出哪些字段、它们如何排序、它们是否分组、选择行的选择标准等等。

Sometimes in this kind of situation it's worth looking at the possibility of generating or modifying XSLT code using XSLT. You can take the parameterization a lot further that way - for example controlling which fields are output, how they are sorted, whether they are grouped, selection criteria for which rows are selected, etc etc.

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