2009-11-16 58 views
0

我使用PHP的simpleXML加載了一個嵌套的簡單XML結構。 結構的某些元素包含「上下文」屬性。通過屬性過濾XML中的結構

<tab context="new_item, edit_item"> 
    <input type="text" context="new_item"> 
    <input type="readonly" context="edit_item"> 
    <tab context="new_item"> 
    ... 
    </tab> 
</tab> 

加載後,我需要清除不屬於當前上下文的所有元素的結構。

我當然可以遍歷每個元素,但也許有人知道快速,SimpleXML的方式 - 可能與XPath - 相應地過濾結構?如果必要的話

context_new_item="yes" context_edit_item = "no" 

注意,「上下文」是一個逗號分隔值列表,但是我可以改變成更可解析的形式。

我通過SimpleXML的文檔自己現在過篩,它只是不PHP文檔的最廣泛的部分...

更新:這篇文章是很難13分鐘老,並在谷歌已經第二爲「simplexml過濾」。該死,我印象深刻。

回答

1

如果您必須通過整個文檔進行過濾,那麼XPath是最佳選擇。問題是SimpleXML不能刪除像這樣的任意節點,所以你必須convert them to DOM,然後使用parentNode-> removeChild()

我正在執行一個類庫的事情,SimpleDOM。以下是我想做到這一點:

include 'SimpleDOM.php'; 

$tab = simpledom_load_string(
    '<tab context="new_item,edit_item"> 
     <input type="text" context="new_item" /> 
     <input type="readonly" context="edit_item" /> 
     <tab context="new_item"> 
     ... 
     </tab> 
    </tab>' 
); 

$context = 'new_item'; 

// will match ",new_item," to ",new_item,edit_item," 
$tab->deleteNodes('//*[contains(concat(",", @context, ","), ",' . $context . ',")]'); 

echo $tab->asXML(); 

注意,它會刪除根節點,因爲它會使文件無效。如果您不想依賴外部庫,請隨時查看源代碼並複製/粘貼您所需的內容。

關於XPath表達式的注意事項:如果值之間用逗號分隔,請確保除逗號(無空格)外沒有其他字符,並將屬性值和匹配它的值放在逗號之間。

+0

xpath-only方法沒有工作,因爲它沒有保存我的樹結構。我現在使用簡單的,很好用 - 謝謝。 – 2009-11-16 20:33:29

1

如果你在你的PHP應用程序「背景」的價值,你可以選擇:

$context = "new_item"; 
$xpath = "//*[not(contains(concat(',', normalize-space(@context), ','), ',$context,'))]"; 

現在你已經選擇了一切,這是在所需的環境下。現在

,如果你有這樣的結構:

<tab context="new_item, edit_item"> 
    <context name="new_item" /> 
    <context name="edit_item" /> 
    <input type="text"> 
    <context name="new_item" /> 
    </input> 
    <input type="readonly"> 
    <context name="edit_item" /> 
    </input> 
    <tab> 
    <context name="new_item" /> 
    ... 
    </tab> 
</tab> 

你可以做更簡單,更高效:

$context = "new_item"; 
$xpath = "//*[not(context[@name='new_item'])]"; 

你也可以使用專用的屬性,如果可能的上下文的數量是有限的。

$context = "new_item"; 
$xpath = "//*[not(context_$context = 'yes')]"; 
+1

Wrt上下文中,使用子元素枚舉上下文使匹配更容易,更新風險更小。另一方面,它更冗長,所以你可能更喜歡使用名稱空間屬性,例如'' – 2009-11-16 15:07:52

+0

這兩個很好的答案,謝謝,我現在看看我是如何構建它們的。 – 2009-11-16 15:12:17