node name expressions attribute and xslt xpath xmlnode

xslt - name - Igualar condicionalmente el valor del nodo actual



xpath value (5)

Creo que lo que realmente quería era el reemplazo en la coincidencia para el nodo "actual", no una coincidencia en el nodo persona:

<xsl:variable name="login" select="//current/login_name/text()"/> <xsl:template match="current/login_name"> <xsl:value-of select=''concat(../../people/person[login_name=$login]/first," ", ../../people/person[login_name=$login]/last)''/> </xsl:template>

Dado el siguiente XML:

<current> <login_name>jd</login_name> </current> <people> <person> <first>John</first> <last>Doe</last> <login_name>jd</login_name> </preson> <person> <first>Pierre</first> <last>Spring</last> <login_name>ps</login_name> </preson> </people>

¿Cómo puedo obtener "John Doe" desde el actual / login matcher?

Intenté lo siguiente:

<xsl:template match="current/login_name"> <xsl:value-of select="../people/first[login_name = .]"/> <xsl:text> </xsl:text> <xsl:value-of select="../people/last[login_name = .]"/> </xsl:template>


Definiría una clave para indexar a las personas:

<xsl:key name="people" match="person" use="login_name" />

El uso de una clave aquí simplemente mantiene el código limpio, pero también puede ser útil para la eficiencia si a menudo tiene que recuperar los elementos <person> función de su hijo <login_name> .

Tendría una plantilla que devolvía el nombre formateado de una <person> :

<xsl:template match="person" mode="name"> <xsl:value-of select="concat(first, '' '', last)" /> </xsl:template>

Y luego haría:

<xsl:template match="current/login_name"> <xsl:apply-templates select="key(''people'', .)" mode="name" /> </xsl:template>


Desea current() función current()

<xsl:template match="current/login_name"> <xsl:value-of select="../../people/person[login_name = current()]/first"/> <xsl:text> </xsl:text> <xsl:value-of select="../../people/person[login_name = current()]/last"/> </xsl:template>

o un poco más limpio:

<xsl:template match="current/login_name"> <xsl:for-each select="../../people/person[login_name = current()]"> <xsl:value-of select="first"/> <xsl:text> </xsl:text> <xsl:value-of select="last"/> </xsl:for-each> </xsl:template>


Si necesita acceder a múltiples usuarios, entonces el enfoque de JeniT <xsl:key /> es ideal.

Aquí está mi alternativa:

<xsl:template match="current/login_name"> <xsl:variable name="person" select="//people/person[login_name = .]" /> <xsl:value-of select="concat($person/first, '' '', $person/last)" /> </xsl:template>

Asignamos el nodo <person> seleccionado a una variable, luego usamos la función concat() para generar los primeros / apellidos.

También hay un error en su XML de ejemplo. El nodo <person> termina incorrectamente con </preson> (error tipográfico)

Podría darse una mejor solución si conociéramos la estructura general del documento XML (con nodos raíz, etc.)


Solo para agregar mis pensamientos a la pila

<xsl:template match="login_name[parent::current]"> <xsl:variable name="login" select="text()"/> <xsl:value-of select=''concat(ancestor::people/child::person[login_name=$login]/child::first/text()," ",ancestor::people/child::person[login_name=$login]/child::last/text())''/> </xsl:template>

Siempre prefiero usar los ejes explícitamente en mi XPath, más humilde pero más claro en mi humilde opinión.

Dependiendo de cómo se vea el resto de los documentos XML (suponiendo que esto sea solo un fragmento) es posible que deba restringir la referencia a "antepasado :: personas", por ejemplo, usando "antepasado :: personas [1]" para restringir a las primeras personas antepasado.