2009-11-16 3 views
0

У меня есть вложенная простая структура XML, которую я загружаю с помощью простого XML-кода PHP. Некоторые элементы структуры содержат атрибуты «контекст».Фильтрация структуры в 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 ...

Update: Это сообщение вряд ли 13 минут назад, а уже второй на Google для «фильтрации симплекс». Черт, я впечатлен.

ответ

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 не работает, потому что он не сохраните мою древовидную структуру. Сейчас я использую упрощение, отлично работает - спасибо. –

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, используя дочерние элементы для перечисления контекстов, упрощает сопоставление и менее рискованно обновлять. С другой стороны, это более подробно, поэтому вы можете использовать атрибуты с именами, например.'' –

+0

Оба замечательных ответа, спасибо, и теперь я посмотрю, как я их создаю. –

Смежные вопросы