2009-04-06 81 views
18

Necesito contar la cantidad de elementos en un archivo XML que tienen un valor particular (para verificar la exclusividad). El archivo XML se ve así:Elementos de conteo XSLT con un valor dado

EDIT: Actualicé el XML original "simplificado" con el verdadero desastre peludo que alguien diseñó. Desafortunadamente, esto hará que todas las respuestas anteriores sean realmente confusas y erróneas a menos que se editen.

<root> 
    <ac> 
    <Properties> 
    <Property Name="Alive"> 
     <Properties> 
     <Property Name="ID"> 
     <Properties> 
      <Property Name="Value"> 
      <long>11007</long> 
      </Property> 
     </Properties> 
     </Property> 
     </Properties> 
    </Property> 
    <Property Name="Dead"> 
     <Properties> 
     <Property Name="ID"> 
     <Properties> 
      <Property Name="Value"> 
      <long>11008</long> 
      </Property> 
     </Properties> 
     </Property> 
     </Properties> 
    </Property> 
    ... 
    <Property Name="MostlyDeadAllDay"> 
     <Properties> 
     <Property Name="ID"> 
     <Properties> 
      <Property Name="Value"> 
      <long>99001</long> 
      </Property> 
     </Properties> 
     </Property> 
     </Properties> 
    </Property> 
    </Properties> 
    </ac> 
</root> 

estoy tratando de definir una variable para ver cómo muchas de las propiedades a nivel Alive/Dead tiene el valor largo (ID) como se define en un parámetro de plantilla. Algo a lo largo de estas líneas (aunque sospecho que esto está mal) ...

<xsl:param name="parPropId"/> 
<xsl:variable name="countProperties"> 
    <xsl:value-of select="count(/root/ac/ 
     Properties/Property/ 
     Properties/Property[@Name = 'ID']/ 
     Properites/Property[@Name = 'Value']/long = $parPropId)"/> 
</xsl:variable> 

No puede haber múltiples elementos de propiedad definida en el nivel "ID". Pero estoy bastante seguro de que puedo contar con un solo elemento de propiedad ("Valor") en "ID", y solo un elemento "largo" en "Valor".

[cláusula de exención de responsabilidad] Quien diseñó el archivo XML en general, estoy trabando con REALMENTE no sabía cómo estructurar XML (por ejemplo, uso de atributos hacia atrás versus elementos). Me temo que mi pensamiento XSLT se ha deformado temporalmente :) como resultado. [/ disclaimer]

+0

¿Por qué la expresión XPath ha mostrado "incorrecta"? No veo nada malo con eso. – Cerebrus

+0

No estoy seguro. Simplifiqué el XML de arriba. El xpath real es este: "/// Properties/Property/Properties/Property [@Name = 'ID']/Properties/Property [@Name = 'Value']/long". Si está en lo cierto, podría reemplazar "/ long" con "[long = $ parPropId]". Parece incorrecto ya que eso pondría dos operaciones "[]" juntas. –

+0

Verifiqué que el texto de vartec() da el texto correcto (es decir, "/// Propiedades/Propiedad/Propiedades/Propiedad [@Name = 'ID']/Propiedades/Propiedad [@Name = 'Valor']/largo/texto () "obtiene mi ID, pero mi conteo usando su método todavía está fallando. –

Respuesta

36

Este XPath:

count(//Property[long = '11007']) 

devuelve el mismo valor que:

count(//Property/long[text() = '11007']) 

... excepto que el primero cuenta Property nodos que coinciden con el criterio y el segundo cuenta long nodos secundarios que coinciden con el criterio.

Según su comentario y la lectura de su pregunta un par de veces, creo que desea encontrar la singularidad en función de una combinación de criterios. Por lo tanto, en realidad, creo que en realidad estás controlando múltiples condiciones. El siguiente funcionaría así:

count(//Property[@Name = 'Alive'][long = '11007']) 

porque significa lo mismo que:

count(//Property[@Name = 'Alive' and long = '11007']) 

Por supuesto, habría que sustituir los valores para los parámetros en su plantilla. El código anterior solo ilustra el punto.

EDITAR (después de la pregunta de edición)


usted razón de ser horrible, el XML. ¡De hecho, este es un candidato francamente CodingHorror! Tenía que seguir contando para hacer un seguimiento del nodo "Propiedad" en el que estaba actualmente. ¡Siento tu dolor!

Aquí van:

count(/root/ac/Properties/Property[Properties/Property/Properties/Property/long = $parPropId]) 

Tenga en cuenta que he eliminado todos los otros controles (para la identificación y valor). Parece que no son necesarios ya que puede llegar al nodo relevante utilizando la jerarquía en el XML. Además, ya mencionó que el control de exclusividad se basa únicamente en el contenido del elemento long.

+0

¡Gracias por educarme en esta equivalencia xpath! Todo lo que ustedes dicen tiene mucho sentido (basado en mi moderada experiencia XSL/XPath). En realidad, no tengo múltiples criterios, la identificación es todo lo que me importa. Simplemente no puedo obtener esa cuenta para dar un valor distinto de cero [arrrgghh]. –

+0

Sorprendentemente, estos comodines a veces usan 'cadena' y 'int' en lugar de sólo 'largo' para estas identificaciones. ¡Me tienes motivado para enviar a CodingHorror! Terminé eliminando la porción '/ larga' de su solución (que ahora funciona). Estoy señalando esto como LA respuesta, y le agradezco a un millón por soportarlo. –

-2
<xsl:variable name="count" select="count(/Property/long = $parPropId)"/> 

No probado, pero creo que debería funcionar. Estoy asumiendo que los nodos de propiedad son hijos directos del nodo raíz y por lo tanto sacar el selector de descendiente de peformance

2

Su XPath es sólo un poco apagado:

count(//Property/long[text()=$parPropId]) 

Editar: Cerebrus señala con razón que el código en su OP (usando el valor implícito de un nodo) está absolutamente bien para sus propósitos. De hecho, dado que es muy probable que desee trabajar con el nodo "Propiedad" en lugar del nodo "largo", probablemente sea superior para solicitar //Property[long=$parPropId] que el texto() xpath, aunque podría argumentar a favor de este último en terrenos de legibilidad

¿Qué puedo decir, estoy un poco cansado hoy :)

+0

¡Adivina qué! ¡Tiene 666 respuestas ahora! Significativo! – Cerebrus

+0

Y, por pura coincidencia, la espalda de Dimitre en su cruzada. – annakata

+0

Y no es coincidencia, Annakata borra nuevamente cualquier comunicación que explica lo que está realmente mal con su respuesta. –

Cuestiones relacionadas