我四处寻找,但未能找到任何可行的想法。
这些是我在 xml 文件(从数据库生成)中的几个节点
<PANELS>
<PANEL ATTR1="7" ATTR2="37" ATTR3="31"/>
<PANEL ATTR1="8" ATTR2="37" ATTR3="31"/>
<PANEL ATTR1="8A" ATTR2="37" ATTR3="31"/>
</PANELS>
<ZONES>
<ZONE ATTR1="7" ATTR2="37" ATTR3="31" />
<ZONE ATTR1="8" ATTR2="37" ATTR3="31" />
<ZONE ATTR1="8A" ATTR2="37" ATTR3="31" />
</ZONES>
我希望能够从其中选择不同的 ATTR3。
目前,这适用于第一个
//PANELS/PANEL[not(@ATTR3 = (前面::*/@ATTR3))]
并返回“31”的预期结果
但是当我尝试对第二个执行相同操作时,它什么也没有返回(我希望它再次返回“31”)
//ZONES/ZONE[not(@ATTR3 = (前面::*/@ATTR3))]
我知道第二个不起作用,因为 ATTR3 的值对于所有节点来说都是相同的,但是如何获取每个节点的不同属性值?
(这被用作 for-each 的谓词,我用它来显示每个不同的值)
它的使用方式如下,其中一个for-each
用于ZONES,另一个用于PANELS
<xsl:for-each select="//PANELS/PANEL[not(@ATTR3 = (preceding::*/@ATTR3))]">
<xsl:sort select="@ATTR3"/>
<xsl:value-of select="@ATTR3" />
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
我希望它返回
PANELS: 31
ZONES: 31
我尝试使用preceding-sibling
而不是preceding
,但后来我得到了
PANELS: 31, 31
ZONES: 31
每个模板都在这样的模板中:
<xsl:template match="//HEADER/ZONES" >
<fo:block font-size="10pt">
<fo:table table-layout="fixed" >
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-column column-width="proportional-column-width(7)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell border-bottom="none">
<fo:block font-weight="bold">
<xsl:text>Zones:</xsl:text>
</fo:block>
</fo:table-cell >
<fo:table-cell>
<fo:block>
<xsl:for-each select="//HEADER/ZONES/ZONE[not(@ATTR3 = (preceding-sibling::*/@ATTR3))]">
<xsl:sort select="@ATTR3"/>
<xsl:value-of select="@ATTR3" />
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</xsl:template>
最佳答案
以下 XSLT 使用 preceding-siblings
而不是 preceding
,因此生成 31 的正确重复次数:
<?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:template match="//HEADER/ZONES">
ZONES:
<xsl:for-each select="//ZONES/ZONE[not(@ATTR3 = (preceding-sibling::*/@ATTR3))]">
<xsl:sort select="@ATTR3"/>
<xsl:value-of select="@ATTR3" />
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="//HEADER/PANELS">
PANELS:
<xsl:for-each select="//PANELS/PANEL[not(@ATTR3 = (preceding-sibling::*/@ATTR3))]">
<xsl:sort select="@ATTR3"/>
<xsl:value-of select="@ATTR3" />
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
本文档的输出:
<HEADER>
<PANELS>
<PANEL ATTR1="7" ATTR2="37" ATTR3="31"/>
<PANEL ATTR1="8" ATTR2="37" ATTR3="31"/>
<PANEL ATTR1="8A" ATTR2="37" ATTR3="31"/>
</PANELS>
<ZONES>
<ZONE ATTR1="7" ATTR2="37" ATTR3="31" />
<ZONE ATTR1="8" ATTR2="37" ATTR3="31" />
<ZONE ATTR1="8A" ATTR2="37" ATTR3="31" />
</ZONES>
</HEADER>
如下:
ZONES:
31
PANELS:
31
关于xslt - XPath 1.0 选择 sibling 的不同属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11363678/