2009-06-08 54 views
6

所有優秀的答案!但問題值得細化...使用嵌套XPath謂詞...精製

我已經得到了下面的示例XML ...

<objects> 
    <object objectId="1123" ... /> 
    <properties refObjectId="1123" ... /> 
    <properties refObjectId="1123" refPropertyId="2311" ... /> 
    <properties refObjectId="1123" refPropertyId="4611" ... /> 
    <object objectId="2123" ... /> 
    <properties refObjectId="2123" refPropertyId="4311" ... /> 
    <properties refObjectId="2123" refPropertyId="8611" ... /> 
    .... 
</objects> 

...和下​​面的XPath查詢...

//object[//properties[@[email protected] and not(@refPropertyId)]] 

我想此查詢將返回所有object節點,其中有一個properties節點,該節點的refObjectId屬性等於object節點objectId屬性,並且沒有'refPropertyId'屬性bute ...只是對象1123,而不是對象2123 ...但它沒有。看起來嵌套謂詞中的@objectId沒有引用object節點的objectId屬性。

任何想法?我知道XML結構沒有像你期望的那樣嵌套,但是這種結構是有原因的。

+0

對象節點中是否有多個對象節點,其中特定對象的屬性發生在對象下方? – 2009-06-08 05:01:39

回答

7

一般而言,您應儘可能避免使用//。我會考慮換一種方式表述:

//object[../properties/@[email protected]] 

在提供的表情,你的嵌套的謂詞實際上是檢查

//properties/@refObjectId=//properties/@objectId 

其中有沒有。

我希望這有助於!

編輯:由於問題已更新此處是更新的響應: 您添加了「看起來嵌套謂詞中的@objectId不引用對象節點的objectId屬性。」你是絕對正確的!所以我們來修復它!

//object[../properties[not(@refPropertyId)]/@[email protected]] 

這應該更接近你以後的!

+1

Nice XPath,Jweede。 – 2009-06-08 05:07:39

0

試試這個:

//objects[object/@objectId = properties/@refObjectId]/object 
0

這應該工作:

//objects/object[@objectId = ../properties/@refObjectId] 

我不知道你的XML是如何。但是,如果是按以下格式:

<objects> 
    <object objectId="1111" /> 
    <properties refObjectId="1111" /> 
    <object objectId="2111" /> 
    <properties refObjectId="3111" /> 
    <object objectId="4111" /> 
    <properties refObjectId="5111" /> 
    <object objectId="6111" /> 
    <properties refObjectId="4111" /> 
    <object objectId="7111" /> 
    <properties refObjectId="7111" /> 
</objects> 

那麼你應該使用以下XPath只得到對象1111和7111的結果應該不包括4111,因爲在那裏refObjectId = 4111不緊跟屬性objectId = 4111的對象。

//objects/properties[@refObjectId = preceding::object[1]/@objectId]/preceding::object[1] 
0

假定屬於特定<object>所有<properties>節點實際上遵循該對象(你的輸入似乎暗示),你可以這樣做:

/objects/properties[ 
    @refObjectId = preceding-sibling::object[1]/@objectId 
    and 
    not(@refPropertyId) 
]/preceding-sibling::object[1] 

這應該執行得很好。

如果你碰巧在XSLT,事情就變得簡單了很多:

<xsl:key name="kPropertiesByObjectId" match="properties" use="@refObjectId" /> 

<xsl:template match="object"> 
    <!-- This tests for an empty node-set. Non-empty node sets can only happen 
     for objects with at least one <properties> node without @refPropertyId --> 
    <xsl:if test="key('kPropertiesByObjectId', @objectId)[not(@refPropertyId)]"> 
    <xsl:copy-of select="." /> 
    </xsl:if> 
</xsl:template> 

在XSLT情況下,對象和proerties節點的順序變得無關緊要。