2010-09-24 5 views
12

XML Источник:XPath, чтобы получить элемент с наибольшим ID

<documents> 
    <document> 
     <id>3</id> 
    </document> 
    <document> 
     <id>7</id> 
    </document> 
    <document> 
     <id>1</id> 
    </document> 
</documents> 

Мне нужен документ-элемент с наибольшим значением в его Ид элемента (так <document><id>7</id></document> в примере). Я не могу изменить код C#, это XMLDocument.SelectSingleNode(...), я могу только изменить используемый XPath.

Есть ли что-то вроде documents/document[id=max(id)] или как order by id descending, чтобы получить его?

ответ

24
documents/document[not(../document/id > id)] 
+2

+1 Для кратчайшего и правильного выражения XPath 1.0, помимо сложности cuadratic ... – 2010-09-24 12:13:28

+0

спасибо, отличное решение, вы должны получить бонусные баллы за этот! – Hinek

+2

Умное решение! –

1

Имейте gander по этой ссылке. Использует функцию math: max().

Существует прямую связь для источника для этой функции и объясняет, как он может быть реализован

http://www.exslt.org/math/functions/max/index.html

Надеется, что это не помогает вам

+0

И после реализации этого вы можете сделать что-то вроде этого:/документы/документ/идентификатор [номер (ребенок :: текст()) <тах (число (ребенок :: текст()))] – Restuta

+0

Что касается как я вижу, он поддерживается несколькими XSLT-процессорами, но не .NET ... Я что-то упустил? – Hinek

+0

@Restuts, мне нужен узел документа, не должен ли это быть больше:/documents/document [number (id/child :: text()) = math: max (number (id/child :: text()))] – Hinek

0

К сожалению, ни XPath 1.0 или XPath 2.0 определяет вид() функция. Однако большинство реализаций имеют вид. Например, <xsl:sort> доступен в реализациях XSLT, а DOM4J имеет сортировку методом XPath. Я уверен, что есть что-то подобное в C#, но вам придется немного изменить код C#.

2

Вы можете использовать preceding и following XPath осей, чтобы проверить, есть ли не большее значение:

XmlDocument doc = new XmlDocument(); 
doc.LoadXml("<documents>" 
    + " <document><id>3</id></document>" 
    + " <document><id>7</id></document>" 
    + " <document><id>1</id></document>" 
    + "</documents>"); 

var max = doc.SelectSingleNode(
    "/documents/document[not(id < preceding::document/id) 
         and not(id < following::document/id)]"); 

Если имеется несколько максимальных значений идентификаторов в документе выше код будет возвращать первый. Если вы хотите, чтобы последний элемент с максимальным идентификатором вы можете использовать

var max = doc.SelectSingleNode(
    "/documents/document[not(id < preceding::document/id) 
         and not(id <= following::document/id)]"); 

Если вы хотите, чтобы получить список всех элементов, имеющих максимальный идентификатор, вы можете использовать SelectNodes метод:

var maxList = doc.SelectNodes(
    "/documents/document[not(id < preceding::document/id) 
         and not(id < following::document/id)]"); 

XSLT версии :

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <root> 
     <xsl:value-of 
      select="/documents/document/id[not(. &lt;= preceding::document/id) 
        and not(. &lt;= following::document/id)]"/> 
     </root> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Разве это не просто даст вам первое, что получилось на том, что было выше, чем раньше, и после него? – jimplode

+0

извините, мой ошибка. – jimplode

11

Кроме того, Ник Джонс XPath 1.0 правильный ответ, в XPath 2.0:

/documents/document[id = max(../document/id)] 
Смежные вопросы