我有一个嵌套的简单XML结构,我使用PHP的simpleXML加载。 结构的某些元素包含“context”属性。
<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”是以逗号分隔的值列表,但我可以将其更改为更易解析的形式:
context_new_item="yes" context_edit_item = "no"
如有必要。
我现在正在自己筛选simpleXML文档,它不是PHP文档中最广泛的部分......
更新:这篇文章不到13分钟,已经在Google上获得第二名“simplexml过滤”。该死的,我印象深刻。
答案 0 :(得分:1)
如果您在PHP应用程序中具有“context”的值,则可以选择:
$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 :(得分:1)
如果你必须过滤整个文档,那么XPath就是你要走的路。问题是SimpleXML无法删除这样的任意节点,所以你必须convert them to DOM然后使用parentNode-&gt; 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表达式的注释:如果用逗号分隔值,请确保除了逗号(没有空格)之外没有其他内容,并将属性的值和您在逗号之间匹配的值括起来。