2014-11-21 5 views
1

Я создаю программу (Visual Studio 2010, .NET 4, консольное приложение на C#) для сбора конкретной информации из общедоступного правительственного отчета, доступного только в виде загрузки xml. Его структура аналогична следующей:Как запросить XML со сложными типами

<Collections> 
<Collection> 
<Info id="123456" address="Some Place" name="Some Name"/> 
<Items> 
<Item1/> 
<Item2/> 
<Item3 I3="Y"/> 
<Item3A I3A1="N" I3A2="N" I3A3 = "Y"/> 
<Item3B I3B1="N" I3B2="N"/> 
<Item4/> 
</Items> 
</Collection> 
<Collection>...</Collection> 
<Collection>...</Collection> 
</Collections> 

Полный файл содержит сотни блоков и находится в диапазоне от 50 до 100 м. Я никогда не работал с XML, отформатированным даже удаленно близко к этому (это выглядит ужасно, правда?), И у вас было много проблем, пытаясь найти любые примеры полезных запросов.

Мне нужно вернуть идентификатор из элемента для всех узлов с «Y» в элементах Item3 через Item3B. Это сводит меня с ума, потому что было бы легко, если бы у них были соответствующие имена элементов и соответствующие атрибуты, но все они уникальны. Вы не можете включить шаблон в запрос XPath, например/Item3 * [Q3 * = "Y"].

Есть ли у кого-нибудь идеи о том, как справиться с этим? Благодаря!

ответ

0

Мне нужно вернуть идентификатор из элемента для всех узлов с «Y» в элементах Item3 через Item3B.

Правильный ответ зависит от точных «правил» для выбора узлов. Неясно, всегда ли вы ищете Item3 через Item3B или если это просто примеры правила. Я также предполагаю, что «узлы имеют« Y »в элементах», вы имеете в виду, что они имеют значение атрибута, равное «Y».

Если вы заинтересованы в точно три узла элементов с точно имена «Item3», «Item3A» и «Item3B», и, если значение «Y» может быть по любому признаку, используйте

//*[self::Item3 or self::Item3A or self::Item3B][@* = 'Y'] 

в противном случае, если правило только говорит, что имена элементов должны начинаться с «ITEM3», используйте

//*[starts-with(name(),'Item3')][@* = 'Y'] 

Если есть пространство имен в вашем входном документе XML, было бы безопаснее использовать функцию local-name() вместо name().

Кажется, вы также пытается сопоставить атрибуты, которые начинаются с определенной строки:

//*[starts-with(name(),'Item3')][@*[starts-with(name(),'Q3')] = 'Y'] 

Как вы можете видеть,

Вы не можете включать подстановочные знаки в Запрос XPath, например/Item3 * [Q3 * = "Y"].

на самом деле не так - есть «подстановочные знаки» (вы обычно не называете их подстановочными знаками), но вам нужен правильный синтаксис.

+0

Это было очень полезно! Я закончил использовать это: // * [start-with (name(), 'Item3')] [@ * [start-with (name(), 'I3')] = 'Y']/ancestor :: Collection/Info/@ id Спасибо! :) –

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