XPath все потомки, даже если они вложены, но не являются потомками родительского

#c# #xpath

#c# #xpath

Вопрос:

Я пытаюсь написать XPath для работы с некоторыми XML-узлами.

Пример моего XML приведен ниже (для имени элемента и иллюстрации вложенности).

 <Forms> 
<Form> 
 <Control/> 
 <Control>   
    <Control></Control> 
 </Control> 
 <Control>
   <Form><!-- This is the nested one, I don't want the Control children from this-->
    <Control/>
   </Form>
 </Control>
</Form>
  

Есть ли способ изменить приведенную ниже инструкцию XPath — включить все элементы управления (даже вложенные друг в друга — под «Формой», но не из вложенной формы (см. Форма<2>)? Этот текущий XPath возвращает «Элементы управления», которые находятся под вложенными узлами «Формы».

 string xpath = @"/Forms/Form[@id='"   node.Attributes["id"].Value   "']//Control[@type='GroupItem' or @type='Detail' or @type='GroupHeader']"; 
  

Я в основном пытаюсь отключить все теги Control и обернуть их тегом «Controls», поэтому я использую этот Xpath в C # для переформатирования — но я не хочу извлекать управление из вложенной формы, я хочу обернуть их в тег Controls отдельно.

Спасибо за любую помощь!

Комментарии:

1. Пожалуйста, предоставьте полный пример XML-документа (как можно меньшего размера) и выражения XPath, сгенерированного вашим кодом, которое фактически вычисляется. Также предоставьте информацию, какие именно элементы были выбраны.

Ответ №1:

В XPath 2.0

 //Control except //Form//Form//Control
  

или в XPath 1.0

 //Control[not(ancestor::Form/ancestor::Form)]
  

Ответ №2:

Как насчет:

  /Forms/Form[@id='blah']/descendant::Control[blah]
  

при этом используется descendant ось при поиске элемента управления (по умолчанию child )

Очевидно, замените blah — они просто для краткости; важная вещь в приведенном выше descendant::

Комментарии:

1. Я что-то пропустил в примере, в других формах есть вложенная «Форма». Я хочу, чтобы все элементы управления находились где-то под формой, но ни один из них не находился под вложенной формой. Итак, если форма имеет вложенную форму, я хочу, чтобы все элементы управления находились в форме, но не элементы управления в ее вложенной форме.

2. @user53885 — с этим дополнительным, возможно, будет проще сделать это в обычном коде… Вы могли бы сделать это в xpath, но это очень нетривиально

Ответ №3:

Это было бы Control s только с одним Form предком:

 //Control[count(ancestor::Form)=1]
  

Редактировать: Лучше

 //Control[not(ancestor::Form[2])]