Xpath:父元素包含1“abc”元素的元素“abc”的数量

时间:2014-10-16 15:27:24

标签: xml xslt xpath

假设我有以下XML:

<elementList id="1">
    <everything>
        <owned>no</owned>
    </everything>
    <elementList id="2">
        <allElements>
            <owned>no</owned>
        </allElements>
        <officeList id="3">
            <room>
                <owned>no</owned>
            </room>
            <furniture>
                <owned>yes</owned>
            </furniture>
        </officeList>
    </elementList>
    <transportation>
        <allCarsOwned>
            <owned>yes</owned>
        </allCarsOwned>
        <cars id="4">
            <truck>
                <owned>yes</owned>
            </truck>
            <motorcycle>
                <owned>yes</owned>
            </motorcycle>
            <familyCar>
                <owned>yes</owned>
            </familyCar>
        </cars>
    </transportation>
</elementList>

我想创建一个XSLT来计算&#34;拥有的&#34;元素,它们拥有的任何名称,以及不拥有的元素,不计算包含其他元素的祖先列表(复合元素)(仅计算包含子元素的终端元素&#34;)。

例如,&#34;拥有&#34;要素是:

furniture, truck, motorcycle, familyCar

同样,&#34;不拥有&#34;要素是:

room

以下元素不应包含在任何列表中:

everything, allElements, allCarsOwned

名称可能会有很大差异,没有规则,我无法通过名称识别它们。

目前,我计算所拥有的所有东西,而不是这样拥有的东西:

    <xsl:variable name="ownedStuff" select="count(//doc:owned[text()='yes'])"/>
    <xsl:variable name="notOwnedStuff" select="count(//doc:owned[text()='no'])"/>

但是这给了我错误的数字。

我宁愿使用以下表达式:

count(//doc:owned[text()='whatever'] and count(//doc:owned::parent::parent:://doc:owned) lt 2)

或者什么......我真的不明白。

有人可以帮助我吗?

.
.
.

情节更改: 非常 难以为每个拥有/不拥有的节点提供整行ID和父节点名称吗?

谢谢大家!

2 个答案:

答案 0 :(得分:0)

如果我理解正确,你想要计算以下元素:

  1. 有一个孩子owned,其值=&#34;是&#34 ;;和
  2. 没有&#34;侄子&#34;除了owned
  3. 之外

    -

    <xsl:value-of select="count(//*[owned='yes' and not(../*/*[not(self::owned)])])"/>
    

    恐怕我不理解这一部分:

      

    情节变化:拥有整行ID非常困难   和每个拥有/不拥有的节点的父节点名称?

答案 1 :(得分:0)

我自己找到了这两种解决方案,感谢Google和空闲时间!

首先,我要感谢@BallaR对另一个问题的回答(在stackoverflow.com上):

  

XPath to count the child nodes based on complex filter

他对这个问题的回答是:

count(//ComRequest/root/component[count(compLine)>10])

让我考虑使用复杂的选择,这就是诀窍!感谢上帝这样的想法是可能的......自从我使用XSLT已经超过5年了,我不能相信我已经忘记了这么快。

使用复杂过滤器计算节点的解决方案是:

count(//doc:owned[text()='whatever' and count(../..//doc:owned[text()='whatever']) lt 2])

现在我必须看看我是否能够枚举每个拥有元素的所有祖先。

.
.
.

事实上,也可以获得所有祖先的名字,不管是什么&#34;拥有节点(通常&#34;不是&#34;在我的情况下拥有):

<xsl:for-each select="//doc:owned[text()='whatever' and count(../..//doc:owned[text()='whatever']) lt 2]">
    <xsl:value-of select="position()"/>. 
    <xsl:value-of select="name(..)"/>
    <xsl:if test="../@Id">
        (#<xsl:value-of select="../@Id"/>)
    </xsl:if>
    <xsl:call-template name="while">
        <xsl:with-param name="parentNode" select="../.."/>
    </xsl:call-template>
</xsl:for-each>

<xsl:template name="while">
    <xsl:param name="parentNode"/>
    <xsl:if test="name($parentNode) != ''"> <!-- to avoid root and document nodes -->
        [<xsl:value-of select="name($parentNode)"/>
        <xsl:if test="$parentNode/../@Id">
            (#<xsl:value-of select="$parentNode/../@Id"/>)
        </xsl:if>]
        <xsl:if test="$parentNode/..">
            <xsl:call-template name="while">
                <xsl:with-param name="parentNode" select="$parentNode/.."/>
            </xsl:call-template>
        </xsl:if>
    </xsl:if>
</xsl:template>

我很高兴XSLT存在:)

向大家致意!