提问人:Pekka 提问时间:11/16/2009 最后编辑:Pekka 更新时间:11/16/2009 访问量:635
按属性筛选 XML 中的结构
Filtering a structure in XML by attribute
问:
我有一个嵌套的简单XML结构,我用PHP的simpleXML加载它。 结构的某些元素包含“上下文”属性。
<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 过滤”。该死的,我印象深刻。
答:
如果你的 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')]";
评论
<input type="readonly" context:edit_item="1" />
如果您必须过滤整个文档,那么 XPath 就是您的不二之选。问题是 SimpleXML 无法像这样删除任意节点,因此您必须将它们转换为 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 表达式的说明:如果值用逗号分隔,请确保只有逗号(没有空格),并在逗号之间将属性的值和要匹配的值括起来。
评论
上一个:重置页面某个区域的 CSS?
评论