尝试使用变量元素名称打印 XSLT 中的节点值
那么这几天有一个问题一直困扰着我。它应该相当容易,但 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,FailedDev 是对的。有人会为你写:
一点解释。
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:
Bit of explanation. The
xsl:for-each
is gonna select each element in the currentrfb2_item
for which the local name is contained in theoutputElements
parameter, or for which theoutputElements
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 inoutputElements
. 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 yieldFUND_ID,SEC_ID
for thesubstring-before
function, which in turn would yield 14 as string length. This is higher than the 8 that you'd get forSEC_ID
, meaning theVALDATE
value is ordered afterSEC_ID
.After the
xsl:sort
, we're simply usingxsl: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 ofxsl: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 theif 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.
有时在这种情况下,值得考虑使用 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.