2011-02-04 2 views
3

Мне нужна помощь, использующая xpath для исключения определенных узлов из списка узлов xml. Структура xml приведена ниже. Файл xml большой, около 8000 элементов, большинство из которых являются подменю.Как использовать предикаты xpath для исключения всех узлов, кроме тех, которые соответствуют условию?

<Menu> 
    <MenuId>2905</MenuId> 
    <Item> 
    <ItemId>191916</ItemId> 
    <ItemType>content</ItemType> 
    </Item> 
    <Item> 
    <ItemId>17343</ItemId> 
    <ItemType>submenu</ItemType> 
    <Menu> 
     ... 
    </Menu> 
    </Item> 
</Menu> 

Что мне нужно сделать, это для определенного MenuID (2905, например) исключить все дочерние узлы, за исключением тех, где ItemType = «содержание»

Я думал, что ниже будет работать?

Menu[MenuId !='2905' or MenuId = '2905' and child::ItemType = 'content']/Item 

Не следует, что выбрать все узлы, которые не в 2905 и любые, которые в 2905 и типа контента? Использование .NET Я пробовал ниже:

 XmlNodeList nextLevelNodeList = currentNode.SelectNodes(string.Format("Menu[MenuId !='2905' or MenuId = '2905' and child::ItemType = 'content']/Item)); 

Любые идеи, было бы весьма признателен ...

веселит Натан

ответ

1

Оба предыдущих ответа неверны.

Использование (от родителя из Menu элементов):

Menu[not(MenuId = 2905)]/Item 
| 
Menu[MenuId = 2905]/Item[ItemType='content'] 
+0

Привет @Dimitre Это будет работать, но я не уверен, как перевести выражение в мое определение NodeList XmlNodeList nextLevelNodeList = currentNode.SelectNodes (string.Format ("Меню/Пункт [ItemLevel = {0}]", iLevel)); Я не могу использовать оператор или в string.format, могу ли я? – Nathan

+0

@Nathan: Конечно, вы можете - это часть строки: 'string.Format (« Menu [not (MenuId = {0}) | Menu [MenuId = {0}]/Item [ItemType = 'content' ]] ", iLevel)' BTW это не "или", а оператор объединения. –

+0

Ницца, отлично работает. Чтобы еще больше усложнить его, могу ли я сохранить серию MenuIds в массиве и использовать это в string.Format? Как и псевдокод ниже ... int [] menuIdArray = {2905, 323, 43453}; Меню [нет (MenuId в MenuIdArray) Думать, что было бы разумно, если бы в будущем были доступны меню, позволяющие применять решение на нескольких меню – Nathan

0

Объединить два узла списка:

Menu[MenuId != '2905']/Item 

И

Menu[MenuId = '2905']/Item[ItemType = 'content'] 
+0

ok. как бы я это сделал? – Nathan

2

прибавлением к списку XPath выражений, без заданного узла объединения:

//Menu/Item[../MenuId != 2905 or ItemType = 'content'] 

Значение: от любого Menu элемент, Item ребенок, имеющий родственника MenuId не равно 2905 или ItemType ребенок равен 'content'

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