开始使用XSLT,这很有趣,我喜欢校长虽然需要一点时间来习惯。现在......我已经遇到了一个我想知道的问题,也许有人可以启发我。
我有一组优先级的盒子。首先显示优先级较低的框。这非常有效。但是,我想把我的盒子放在一排,排成1行和1行。 3标记为奇数,第2行标记为偶数(我预计在实际项目中会有更多行。)
因此,我认为我应该可以使用fn:position()函数。不幸的是,返回的位置是原始节点之一,而不是生成的排序节点。有没有办法解决这个问题?
有一个示例XSLT公开了问题:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="body">
<xsl:apply-templates>
<xsl:sort select="@priority" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="body/box">
<div class="box">
Box[<xsl:value-of select="count(preceding-sibling::box) + 1" />,<xsl:value-of select="position()"/>] = (<xsl:value-of select="@priority"/>)
<xsl:copy-of select="title"/></div>
</xsl:template>
</xsl:stylesheet>
还有一个输入的例子。两个应首先出现,然后是三个,最后出现一个。
<?xml version="1.0"?>
<body>
<box priority="103">
<title>This is box ONE</title>
</box>
<box priority="1">
<title>This is box TWO</title>
</box>
<box priority="12">
<title>This is box THREE</title>
</box>
</body>
但我希望position()为1,2和3 ......但这是输出:
<div class="box">
Box[2,4] = (1)
<title>This is box TWO</title>
</div>
<div class="box">
Box[3,6] = (12)
<title>This is box THREE</title>
</div>
<div class="box">
Box[1,2] = (103)
<title>This is box ONE</title>
</div>
Box方括号内的第二个数字是位置()。我被期待1,2,3。但是正如我们所看到的,我们得到4,6,2这是原始文档中节点的位置(我不太确定为什么它是x2但是当我测试时xsl:for-each标签,而不是2,3和1。)
我测试了xmlpatterns(Qt 4.7)和xsltproc(libxml2,这应该使用版本1.0,代码与1.0兼容)并且都返回相同的数字。
那么......是XSLT的限制,还是这两个XSLT实现中的错误?!
2012年5月27日更新
在特定情况下,确定QXmlQuery(xmlpatterns)是一个破解的解析器。必须使用类似于count(preceding-sibling::box) + 1
的东西计算position(),而不是运行for-each或模板序列中的正确索引。
答案 0 :(得分:2)
嗯,你做
<xsl:apply-templates>
<xsl:sort select="@priority" data-type="number"/>
</xsl:apply-templates>
这是做
的缩写<xsl:apply-templates select="node()">
<xsl:sort select="@priority" data-type="number"/>
</xsl:apply-templates>
处理所有类型的子节点,包括您似乎感兴趣的元素节点以及元素之间的空白文本节点。所以使用
<xsl:apply-templates select="box">
<xsl:sort select="@priority" data-type="number"/>
</xsl:apply-templates>
你应该至少将position()设置为1,2,3,如你所愿。
为了它的价值,我在Windows上使用样式表
测试了xsltproc<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="body">
<xsl:apply-templates select="box">
<xsl:sort select="@priority" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="body/box">
<div class="box">
Box[<xsl:value-of select="count(preceding-sibling::box) + 1" />,<xsl:value-of select="position()"/>] = (<xsl:value-of select="@priority"/>)
<xsl:copy-of select="title"/></div>
</xsl:template>
</xsl:stylesheet>
针对您发布的输入,结果为
compilation error: file test2012052702.xsl line 2 element stylesheet
xsl:version: only 1.0 features are supported
<?xml version="1.0"?>
<div class="box">
Box[2,1] = (1)
<title>This is box TWO</title></div><div class="box">
Box[3,2] = (12)
<title>This is box THREE</title></div><div class="box">
Box[1,3] = (103)
<title>This is box ONE</title></div>
所以我认为这个立场是正确的。
答案 1 :(得分:1)
无法重现。
我使用Saxon 9.1.07进行转换,结果是;
<div class="box">
Box[2,5] = (1)
<title>This is box TWO</title></div><div class="box">
Box[3,6] = (12)
<title>This is box THREE</title></div><div class="box">
Box[1,7] = (103)
<title>This is box ONE</title></div>
正如我们所见,这些位置是正确的(仍然不是1,2,3 - 因为只有白色空间的节点也存在)。
XQSharp(XmlPrime)也会产生相同的结果。
AltovaXML2009(XML-SPY)甚至产生:
<?xml version="1.0" encoding="UTF-8"?><div class="box">
Box[2,1] = (1)
<title>This is box TWO</title></div><div class="box">
Box[3,2] = (12)
<title>This is box THREE</title></div><div class="box">
Box[1,3] = (103)
<title>This is box ONE</title></div>
这意味着它使用XML解析器来剥离仅限空白的文本节点。
此转换的改进版本将排除仅限空白的节点:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="body">
<xsl:apply-templates>
<xsl:sort select="@priority" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="box">
<div class="box">
Box[<xsl:value-of select="count(preceding-sibling::box) + 1" />
<xsl:text>,</xsl:text>
<xsl:value-of select="position()"/>
<xsl:text>] = (</xsl:text>
<xsl:value-of select="@priority"/>)
<xsl:copy-of select="title"/></div>
</xsl:template>
</xsl:stylesheet>
对提供的XML文档应用此转换时:
<body>
<box priority="103">
<title>This is box ONE</title>
</box>
<box priority="1">
<title>This is box TWO</title>
</box>
<box priority="12">
<title>This is box THREE</title>
</box>
</body>
产生了想要的正确结果:
<div class="box">
Box[2,1] = (1)
<title>This is box TWO</title>
</div>
<div class="box">
Box[3,2] = (12)
<title>This is box THREE</title>
</div>
<div class="box">
Box[1,3] = (103)
<title>This is box ONE</title>
</div>
备注:xsl:strip-space
用于排除仅限空白节点甚至被解析。
结论:报告的结果是使用有缺陷的XSLT处理器,或执行与提供的转换不同的转换。