Как получить последний узел, используя XPath в C #? - PullRequest
6 голосов
/ 24 августа 2011

У меня есть следующая часть XML-файла.

<UN N="@U1">
    <DT N="24/06/2011">
        <PN N="@P1">
            <TM N="02:24:11">
                <JB T="GP">
                    <A>notepad</A>
                    <Z>Notepad</Z>
                    <N>Untitled - Notepad</N>
                    <J>1;0;1;1;0;0</J>
                    <C>0.00500;0.09500;0.03500</C>
                    <S>1;0;1;1</S>
                    <P>0;0</P>
                    <F>0</F>
                </JB>
            </TM>
        </PN>
    </DT>

    <DT N="23/06/2011">
        <PN N="@P1">
            <TM N="02:38:49">
                <JB T="PAGP">
                    <A>notepad</A>
                    <Z>Notepad</Z>
                    <N>Untitled - Notepad</N>
                    <J>1;1;1;1;0;1</J>
                    <C>0.00500;0.09500;0.03500</C>
                    <S>1;1;0;0</S>
                    <P>1;1</P>
                    <F>0</F>
                </JB>
            </TM>               
        </PN>
    </DT>

    .....
    .....

</UN>

Мне нужно получить последний узел, где PN N=@P1.

Пример запроса будет оценен.

Заранее спасибо.

Ответы [ 2 ]

6 голосов
/ 24 августа 2011

Операция XPath:

"/UN/DT[PN/@N='@p1'][last()]"

вернет последний DT узел, для которого PN=@p1.

5 голосов
/ 24 августа 2011

Функция last() XPath может использоваться для поиска последнего из набора узлов. Таким образом, последний <PN> узел с атрибутом N, имеющий значение @P1, будет иметь вид:

//PN[@N='@P1'][position() = last()]

Код .NET будет зависеть от того, какой XML API вы используете: XmlDocument, XPathDocument или LINQ to XML (XDocument). (Подход с XmlReader заключается в загрузке в одну из трех и последующем использовании.)

Редактировать (на основе комментария) Возвращать <F> потомка последнего <PN> с атрибутом, как указано выше, где xDoc является экземпляром XmlDocument:

var foundNode = xDoc.SelectSingleNode("//PN[@N='@P1'][position() = last()]/TM/JB/F");

Редактировать # 2 (на основе другого комментария) : вернуть последний <PN>, где каждый <DT> может содержать несколько <DT> элементов 1 по всем <DT> элементам.

Проверка этого с использованием лучшего образца XML (см. Ниже) с использованием XmlElement.SelectNodes, а затем итерация по возвращенному набору узлов показала, что был найден нужный узел, он просто не был первым и поэтому не возвращается SelectSingleNode. Это подсказка: предикат last() применялся в каждом совпадении //PN[@N='@P1']. Быстрая смена приоритета - все, что было нужно:

(//PN[@N='@P1'])[last()]

1 Для дальнейшего использования, если возможно несколько элементов, укажите хотя бы два в образце, в противном случае читатели примут только единичные экземпляры. Также удалите все узлы (например, дочерние), которые не нужны:

Образец XML, который я использовал для тестирования (добавлены атрибуты x, чтобы упростить идентификацию элемента, выбранного во время тестирования):

<UN N='@U1'>
  <DT N='24/06/2011'>
    <PN N='@P1' x='#1'/>
    <PN N='@P1' x='#2'/>
    <PN N='@P2' x='#3'/>
  </DT>

  <DT N='24/06/2011'>
    <PN N='@P1' x='#4'/>
    <PN N='@P1' x='#5'/>
    <PN N='@P2' x='#6'/>
  </DT>

  <DT N='24/06/2011'>
    <PN N='@P3' x='#7'/>
    <PN N='@P4' x='#8'/>
    <PN N='@P5' x='#9'/>
  </DT>
</UN>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...