xml - tutorial - ¿Cómo reemplazar un nombre de nodo con otro en Xslt?
transformar xml a xslt (3)
¿Por qué no puedes simplemente reemplazar el elemento "KEY" con elementos "STRONG"? Es mejor no pensar demasiado sobre esto.
<xsl:template match="FIELD[@NAME=''body'']">
<xsl:apply-templates/>
<xsl:template>
<xsl:template match="key">
<strong>
<xsl:apply-templates/>
<strong>
</xsl:template>
<xsl:template match="text()">
<xsl:copy-of select="."/>
</xsl:template>
¿O te malentendí?
Mala redacción de la pregunta, perdón por eso. Trataré de explicar lo que trato de hacer. Básicamente tengo el resultado de una búsqueda como Xml y en ese Xml hay un nodo como este:
<FIELD NAME="body">
Somebody named
<key>Doris</key>
and
<key>Arnie</key>
</FIELD>
En resumen, lo que necesito es reemplazar "<key>" con "<strong>"; es decir. resalte los resultados de la búsqueda (los valores del nodo clave son los que el usuario buscó). En Xslt no sé de lo que ha buscado el usuario, aparte de consultar la clave Xml -> FIELD [@ name = ''body''] /.
En este momento tengo un código loco que extraerá lo que esté delante del término de búsqueda ("Doris"), pero que funciona solo para 1 término de búsqueda. Necesitamos que haga esto por múltiples términos. El código que usamos se ve así:
<xsl:template name="highlighter">
<xsl:param name="text"/>
<xsl:param name="what"/>
<xsl:choose>
<xsl:when test="contains($text, $what) and string-length($what) > 0">
<xsl:variable name="before" select="substring-before($text, $what)"/>
<xsl:variable name="after" select="substring-after($text, $what)"/>
<xsl:variable name="real-before" select="substring($text, 1, string-length($before))"/>
<xsl:variable name="real-what" select="substring($text, string-length($before) + 1, string-length($what))"/>
<xsl:variable name="real-after" select="substring($text, string-length($before) + string-length($what) + 1)"/>
<xsl:value-of select="$real-before"/>
<strong>
<xsl:value-of select="$real-what"/>
</strong>
<xsl:call-template name="highlighter">
<xsl:with-param name="text" select="$real-after"/>
<xsl:with-param name="what" select="$what"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Lo que he intentado hacer es llamar este código varias veces con los diferentes términos de búsqueda, pero estoy luchando sobre cómo usar la salida de la llamada a la plantilla como entrada para la próxima llamada. En el código sería algo como esto:
string body = doc.SelectSingleNode("FIELD[@NAME=''body'']");
NodeCollection nodes = doc.SelectNodes("FIELD[@NAME=''body'']/key");
foreach (var node in nodes) {
body = hightlighter(body, node.InnerText);
}
Hasta ahora no he podido hacer algo como esto en XSLT, pero sigo siendo novato, así que ...;)
Editar: solo para aclarar; el resultado que estoy buscando es el siguiente:
Somebody named <strong>Doris</strong> and <strong>Arnie</strong>
Esto debería hacer lo que necesites. Utiliza la plantilla de aplicar en lugar de llamar a plantillas y es una forma más funcional de abordar este problema.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Template to match your ''key'' and replace with strong -->
<xsl:template match="FIELD[@name=''body'']/key">
<strong><xsl:apply-templates select="@*|node()"/></strong>
</xsl:template>
<!-- Template to match all nodes, copy them and then apply templates to children. -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Lo mejor que se puede hacer en tales situaciones es copiar recursivamente los nodos de la entrada a la salida y anular los nodos que desea tratar de manera diferente. La idea clave es que las cadenas de texto son nodos que también se pueden copiar. Aquí hay un ejemplo:
<xsl:template match="key">
<strong>
<xsl:apply-templates select="@*|node()"/>
</strong>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>