2009-11-16 46 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