2010-09-24 64 views
12

XML Fuente:XPath para obtener el elemento con el más alto ID

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

necesito el documento de elementos con el valor más alto de su Identificación de elementos (por lo <document><id>7</id></document> en el ejemplo). No puedo cambiar el código C#, es XMLDocument.SelectSingleNode(...), solo puedo modificar el XPath utilizado.

¿Hay algo así como documents/document[id=max(id)] o como order by id descending para obtenerlo?

Respuesta

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

+1 Para la expresión máxima de XPath 1.0 más corta y correcta, además de la complejidad cuadrática ... –

+0

gracias, gran solución, ¡deberías obtener puntos de bonificación por esta! – Hinek

+2

¡Solución inteligente! –

1

Eche un vistazo en este enlace. Utiliza una función math: max().

Hay un enlace de fuente para esa función y se explica cómo se puede implementar

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

la esperanza que esto le ayuda

+0

Y después de implementar esto se puede hacer algo como esto:/documentos/documento/ID [número (child :: texto()) Restuta

+0

como veo, es compatible con varios procesadores XSLT, pero no con .NET ... ¿Me falta algo? – Hinek

+0

@Restuts, necesito el nodo del documento, ¿no debería ser más como:/documents/document [number (id/child :: text()) = math: max (number (id/child :: text()))] – Hinek

0

Lamentablemente, ni XPath 1.0 o XPath 2.0 definir una especie() función. Sin embargo, la mayoría de las implementaciones tienen un ordenamiento. Por ejemplo, <xsl:sort> está disponible en implementaciones XSLT, y DOM4J tiene una clasificación por método XPath. Estoy seguro de que hay algo similar en C# pero tendrías que cambiar un poco el código de C#.

2

Puede utilizar el preceding y following XPath ejes para comprobar si no hay mayor valor:

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)]"); 

Si hay varios valores máximos en el documento de identificación del código anterior devolverá el primero. Si desea que el último elemento con un ID máximo que se puede utilizar

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

Si desea obtener una lista con todos los elementos que tienen un identificador máximo que puede utilizar el SelectNodes método: Versión

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

¿Esto no solo le daría el primero que cruzó que era más alto que el anterior y el siguiente? – jimplode

+0

lo siento, mi error. – jimplode

11

Además Nick Jones XPath 1.0 respuesta correcta, en XPath 2.0:

/documents/document[id = max(../document/id)] 
Cuestiones relacionadas