2011-08-19 99 views
7

我有類似下面這樣的結構:的XPath:選擇節點,但沒有具體的子元素

<page id='1'> 
    <title>Page 1</title>  
    <page id='2'> 
    <title>Sub Page 1</title> 
    </page> 
    <page id='3'> 
    <title>Sub Page 2</title> 
    </page>  
</page> 
<page id='4'> 
    <title>Page 2</title> 
</page> 

我需要選擇ID的頁面,但如果該頁面有後代頁面我不想回這些元素,但我確實需要該頁面的其他元素。如果我選擇第1頁我想回到標題,但不是孩子的網頁...

//page[@id=1] 

上面讓我第1頁,但我如何排除子頁面?另外,頁面中可以有任意數量的元素。

//page[@id=1]/*[not(self::page)] 

我發現這讓我獲得了我想要的數據。但是,該數據作爲每個元素具有一個對象的對象數組返回,並且顯然排除了元素名稱???。我正在使用PHP SimpleXML來實現它的價值。

+0

問得好,+1。看到我的答案是一個簡短而簡單的解決方案。 :) –

+1

「但是,該數據作爲每個元素具有一個對象的對象數組返回。」這與你想要/需要的有什麼不同? – LarsH

+0

根據xpath查詢,數據以不同的格式返回,我得到一個SimpleXMLElement數組,每個數組中都有一個字符串,並且缺少元素名稱。第一種情況返回一個包含所有預期鍵值對的SimpleXMLElement對象。我不明白爲什麼,也許我會提出另一個問題。 – Ben

回答

7

使用

//page[@id=$yourId]/node()[not(self::page)] 

這裏選擇不page和任何page的子女文檔中的所有節點上,字符串值的id屬性等於$yourId中包含的字符串(很可能您會用上面的$yourId替換爲特定的,所需的字符串,如'1')。

下面是一個簡單的基於XSLT的驗證

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:param name="pId" select="3"/> 

<xsl:template match="/"> 
    <xsl:copy-of select="//page[@id=$pId]/node()[not(self::page)]"/> 
</xsl:template> 
</xsl:stylesheet> 

當該變換被應用所提供的XML文檔(包裝在單個頂節點將其合格的):

<pages> 
    <page id='1'> 
     <title>Page 1</title> 
     <page id='2'> 
      <title>Sub Page 1</title> 
     </page> 
     <page id='3'> 
      <title>Sub Page 2</title> 
     </page> 
    </page> 
    <page id='4'> 
     <title>Page 2</title> 
    </page> 
</pages> 

想要的,正確的結果產生

<title>Sub Page 2</title> 

請注意:做一個假設是,一個id值唯一標識一個page。如果不是這樣,則所提出的XPath表達式將選擇全部page元素,其id屬性的字符串值爲$yourId

如果是這種情況,只有一個page元件必須被選擇,則OP必須指定與此id許多page元件中的一個應該被選中。

例如,它可能是第一個

(//page[@id=$yourId]/node()[not(self::page)])[1] 

或最後

(//page[@id=$yourId]/node()[not(self::page)])[last()] 

或...

+0

儘管這看起來完全正確,但實際上並沒有工作..我不確定在PHP的簡單xml中xpath是否有問題,但是這會返回請求頁面的多個副本? – Ben

+0

@Ben:只有當多個'page'可以具有與'id'屬性相同的值時纔會發生這種情況。我已經更新了我的答案以涵蓋這個案例。我還提供了一個簡單的驗證,表明如果一個'id'值唯一標識一個'page',那麼最初的XPath表達式只選擇一個'page'元素。 –

1

如果你只在標題元素感興趣,這會工作:

//page[@id=1]/title 

然而,如果你需要的頁面的其他子元素,我不知道XPath是適合你的工具。 聽起來更像是XSLT將適合的東西,因爲你真正在做的是改變你的數據。

+0

不幸的是我需要任意數量的任意元素,除了頁面... – Ben

+0

更新的答案與進一步的信息。無論如何,如果它有幫助,請隨時註冊。 :) –

+0

謝謝,我開始認爲Xpath也許不能這樣做。我總是可以寫一些東西來處理我想要的數據,但希望能夠在數據級別完成。 – Ben

0

如果頁面總是有一個標題:

//page[@id='1']/*[not(boolean(./title))] 
相關問題