XPath 1.0选择兄弟姐妹的不同属性 [英] XPath 1.0 select distinct attribute of siblings

查看:94
本文介绍了XPath 1.0选择兄弟姐妹的不同属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经四处寻找,但无法获得我发现可行的任何想法.

I have hunted around, but haven't been able to get any of the ideas I've found to work.

这些是我在xml文件(由数据库生成)中拥有的几个节点

These are a couple of nodes I have in an xml file (that is generated from a db)

<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.

I want to be able to select the distinct ATTR3 from each of these.

当前,这适用于第一个 //PANELS/PANEL[not(@ATTR3 = (preceding::*/@ATTR3))] 并返回预期结果"31"

Currently, this works for the first one //PANELS/PANEL[not(@ATTR3 = (preceding::*/@ATTR3))] and returns the expected result for '31'

但是当我尝试对第二个做同样的事情时,它什么也不返回(我希望它再次返回"31") //ZONES/ZONE[not(@ATTR3 = (preceding::*/@ATTR3))]

But when I try to do the same for the second one, it returns nothing (I want it to return '31' again) //ZONES/ZONE[not(@ATTR3 = (preceding::*/@ATTR3))]

我知道第二个不起作用,因为ATTR3的值对于所有它们都相同,但是如何获得每个节点的不同属性值?

I understand that the second one is not working because the value of ATTR3 is the same for all of them, but how do I get the distinct attribute value per node?

(这被用作我用于显示每个不同值的for-each的谓词)

(This is being used as the predicate for a for-each that I am using to display each distinct value)

以此方式使用,其中for-each之一用于 ZONES ,另一种用于 PANELS

This is being used like this, one of these for-each for ZONES and one for 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,但是随后我得到了

I have tried using preceding-sibling instead of preceding, but then I get

PANELS: 31, 31

ZONES: 31

每个人都在这样的模板中:

Each one is in a template like this:

    <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 :

The following XSLT uses preceding-siblings instead of preceding and thus produces the correct number of repetitions of the 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

这篇关于XPath 1.0选择兄弟姐妹的不同属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆