Xpath, чтобы выбрать все и исключить дочерний элемент и его дочерние элементы

У меня есть данные ниже, и я пытаюсь выбрать все узлы, кроме RejectedRecords и всех его дочерних элементов.

<?xml version="1.0" encoding="UTF-8"?>
<inmsg>
  <BPDATA>
    <DATE_TIME>10072014084945</DATE_TIME>
  </BPDATA>
  <Orders>
    <Rejected>
      <RejectedRecords>
        <RecordNumber>1</RecordNumber>
        <RecordError>State Code is invalid</RecordError>
      </RejectedRecords>
      <RejectedRecords>
        <RecordNumber>2</RecordNumber>
        <RecordError>State Code is invalid</RecordError>
      </RejectedRecords>
      <FileName>Foo1.txt</FileName>
      <MessageType>Rejected</MessageType>
      <RecordCount>2</RecordCount>
      <TotalAmount>1050.01</TotalAmount>
    </Rejected>
    <Unrestricted>
      <FileName>Foo2.txt</FileName>
      <MessageType>UnrestrictedState</MessageType>
      <RecordCount>2</RecordCount>
      <TotalAmount>100.10</TotalAmount>
    </Unrestricted>
  </Orders>
  <PrimaryDocument SCIObjectID="6442821469081a3a3node1"/>
</inmsg>

Я пробовал ряд утверждений, таких как

//*/node()[not(parent::RejectedRecords) and not(self::RejectedRecords) and not(self::RecordNumber) and not(self::RecordError)]
//*[not(parent::RejectedRecords) and not(self::RejectedRecords)]
//*[not(descendant-or-self::RejectedRecords)]

Результаты

Независимо от того, что я использовал, я все еще получаю узел RejectedRecords и его дочерние элементы, потому что он входит с узлом Rejected. Что я делаю не так?


person camarokris    schedule 12.06.2014    source источник
comment
Если вы выберете узел, его дочерние элементы станут его частью. Вы можете выбрать конечные узлы из родителей, например текстовое содержимое родителя (если оно существует) или родительские атрибуты.   -  person helderdarocha    schedule 12.06.2014
comment
Если вы на самом деле имеете в виду выбор всего, кроме поддерева Rejected, вы можете использовать //Orders/*[not(self::Rejected)] | /*/*[not(self::Orders)]   -  person helderdarocha    schedule 12.06.2014
comment
В частности, пытаясь получить все, кроме поддеревьев RejectedRecords   -  person camarokris    schedule 12.06.2014
comment
Я понял. Вы должны проверить узел на наличие предка, а не потомка.   -  person helderdarocha    schedule 12.06.2014


Ответы (2)


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

//*[not(descendant::RejectedRecords) and not(ancestor-or-self::RejectedRecords)]

Вот ссылка на результат в XPath Tester.

person helderdarocha    schedule 12.06.2014
comment
Он по-прежнему возвращает эти данные как часть Rejected и Orders. Тестер XPath - person camarokris; 12.06.2014
comment
Извиняюсь. Забыл также включить ось потомков. В конце концов, необходимо удалить родителя Rejected, который будет включать в себя все его дочерние элементы. Я отредактирую ответ. - person helderdarocha; 12.06.2014

XPath может выбирать только целые поддеревья, но не изменять их или создавать новый вывод XML.

Если вы выберете элемент //Orders, он всегда будет включать элементы <Rejected/>. Все, что вы можете сделать, это, например. выберите все заказы, которые не были отклонены, но при этом вы потеряете узлы вокруг:

//Orders/*[not(self::Rejected)]

В зависимости от того, как вы используете XPath, вы можете использовать его для фактического удаления элементов <Rejected/>, выбрав их с помощью XPath, а затем удалив их с помощью структуры XML вашего основного языка программирования.

Если вы хотите создать новые результаты на языке XML, вы должны использовать шаблоны XSLT или XQuery (что очень близко к XPath). Что лучше подходит для вашей проблемы, зависит от ваших реальных требований и потребностей.

person Jens Erat    schedule 12.06.2014