Foros del Web » Programación para mayores de 30 ;) » Programación General »

Procesar etiqueta dentro de texto - XML -> XSL [Solucionado]

Estas en el tema de Procesar etiqueta dentro de texto - XML -> XSL [Solucionado] en el foro de Programación General en Foros del Web. Buenas. Tengo una cuestión simple pero me doy cuenta que antes no la había intentado. Se trata de que tengo texto dentro de una etiqueta, ...
  #1 (permalink)  
Antiguo 27/11/2008, 17:14
Avatar de jam1138
/** @package Moderador */
 
Fecha de Ingreso: julio-2004
Ubicación: sèveR led onieR lE
Mensajes: 9.368
Antigüedad: 20 años, 4 meses
Puntos: 102
Procesar etiqueta dentro de texto - XML -> XSL [Solucionado]

Buenas. Tengo una cuestión simple pero me doy cuenta que antes no la había intentado. Se trata de que tengo texto dentro de una etiqueta, y dentro de ese texto puede haber otras etiquetas (como los <strong>, <em>, <span> de HTML). Necesito cachar ese texto y tratarlo para igual encerrarlo dentro de otras etiquetas, esta vez tipo BBCode.

He aquí un XML de ejemplo:
Código xml:
Ver original
  1. <?xml version="1.0" ?>
  2. <seccion>
  3.     <title>Titulo</title>
  4.     <para>
  5.         Lorem <def>ipsum</def> postea complectitur eos in, mandamus disputationi
  6.         mediocritatem vix ei.
  7.     </para>
  8. </seccion>

Aquí el XSL que estoy --hasta ahora-- aplicando:
Código xml:
Ver original
  1. <?xml version="1.0" ?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.     <xsl:output method="text"/>
  4.     <xsl:template match="seccion">
  5.         [TITLE]<xsl:value-of select="title"/>[/TITLE]
  6.         <xsl:value-of select="normalize-space(para)" />
  7.     </xsl:template>
  8. </xsl:styleshee

MI salida actual:
Cita:
[TITLE]Titulo[/TITLE]
Lorem ipsum postea complectitur eos in, mandamus disputationi mediocritatem vix ei.
Lo que quiero conseguir (negritas de mi parte):
Cita:
[TITLE]Titulo[/TITLE]
Lorem [DEF]ipsum[/DEF] postea complectitur eos in, mandamus disputationi mediocritatem vix ei.
Entonces, que sé cómo accesar a el contenido de la etiqueta <def> (para/def) pero lo que no se me ocurre ahora es cómo ... tratarlo para que el contenido (el texto) quede de la misma forma, colocarlo en el mismo lugar.

Si alguien me hecha una pista, os agradeceré .
__________________
٩(͡๏̯͡๏)۶
» Cómo hacer preguntas de manera inteligente «

"100 años después, la revolución no es con armas, es intelectual y digital"
  #2 (permalink)  
Antiguo 28/11/2008, 05:17
Avatar de monoswim
$moderador{'Esteban'}
 
Fecha de Ingreso: febrero-2002
Ubicación: Buenos Aires - Argentina
Mensajes: 8.762
Antigüedad: 22 años, 9 meses
Puntos: 90
Respuesta: Procesar etiqueta dentro de texto - XML -> XSL

Una pregunta, porque guardas en el XML <def> si luego debes mostrarlo como [def]...Podrías guardarlo directamente como [def] y mostrar literalmente lo que tiene la etiqueta...

Lo que dices de encontrar los para/def y dejarlos en el mismo lugar NO SE PUEDE hace meses que tuve ese problema y me rompí la cabeza buscando la solución...no la encontré

Te sirve lo que te puse al principio ?

un abrazo grande...

__________________
Esteban Quintana
  #3 (permalink)  
Antiguo 28/11/2008, 12:39
Avatar de jam1138
/** @package Moderador */
 
Fecha de Ingreso: julio-2004
Ubicación: sèveR led onieR lE
Mensajes: 9.368
Antigüedad: 20 años, 4 meses
Puntos: 102
Respuesta: Procesar etiqueta dentro de texto - XML -> XSL

Cita:
Iniciado por monoswim Ver Mensaje
Una pregunta, porque guardas en el XML <def> si luego debes mostrarlo como [def]...Podrías guardarlo directamente como [def] y mostrar literalmente lo que tiene la etiqueta...
¿Te refieres a tener [DEF] en el XML fuente?; no puedo, no tengo control sobre ese contenido :-/.

Se me hace difícil de creer no se pueda. La verdad es que no he visto nada así en los ejemplos de XSL. Intentaré buscarle, sino creo poderlo solucionar echando mano de PHP... a ver qué logro.

__________________
٩(͡๏̯͡๏)۶
» Cómo hacer preguntas de manera inteligente «

"100 años después, la revolución no es con armas, es intelectual y digital"
  #4 (permalink)  
Antiguo 28/11/2008, 18:40
Avatar de jam1138
/** @package Moderador */
 
Fecha de Ingreso: julio-2004
Ubicación: sèveR led onieR lE
Mensajes: 9.368
Antigüedad: 20 años, 4 meses
Puntos: 102
Respuesta: Procesar etiqueta dentro de texto - XML -> XSL

Uf, uf, uf y recontra uf! :

Primero, aunque sabía no iba por ahí, me puse a buscar sobre el reemplazo de cadenas (no va por ahí porque es otro nodo XML, no es solo una cadena) con la esperanza de encontrar algo. Me topé con la función translate(), pero ésta solo reemplaza caracteres, pero teniendo más noción recurrí a Google y encontré una función para remplazar cadenas con xsl que solo copié y pegué (haciendo caso de las instrucciones ):
Código xml:
Ver original
  1. <xsl:template name="replace-string">
  2.   <xsl:param name="text"/>
  3.   <xsl:param name="from"/>
  4.   <xsl:param name="to"/>
  5.  
  6.   <xsl:choose>
  7.     <xsl:when test="contains($text, $from)">
  8.  
  9.       <xsl:variable name="before" select="substring-before($text, $from)"/>
  10.       <xsl:variable name="after" select="substring-after($text, $from)"/>
  11.       <xsl:variable name="prefix" select="concat($before, $to)"/>
  12.  
  13.       <xsl:value-of select="$before"/>
  14.       <xsl:value-of select="$to"/>
  15.       <xsl:call-template name="replace-string">
  16.         <xsl:with-param name="text" select="$after"/>
  17.         <xsl:with-param name="from" select="$from"/>
  18.         <xsl:with-param name="to" select="$to"/>
  19.       </xsl:call-template>
  20.     </xsl:when>
  21.     <xsl:otherwise>
  22.       <xsl:value-of select="$text"/>
  23.     </xsl:otherwise>
  24.   </xsl:choose>
  25.  
  26. </xsl:template>

Para utilizarla, hay que invocar el template de la siguiente manera:
Código xml:
Ver original
  1. <xsl:call-template name="replace-string">
  2.   <xsl:with-param name="text" select="path/del/nodo"/>
  3.   <xsl:with-param name="from" select="'textoAbuscar'"/>
  4.   <xsl:with-param name="to" select="'textoParaReemplazar'"/>
  5. </xsl:call-template>

Entonces, yo solo tomo el contenido del nodo, y lo reemplazo por sí mismo concatenado con el BBCode correspondiente (se me ocurrió, cualquier otra idea es bienvenida). Entonces, el XSL me quedó de la siguiente manera:
Código xml:
Ver original
  1. <?xml version="1.0" ?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3. <xsl:output method="text"/>
  4.  
  5. <xsl:template match="seccion">
  6.     [TITLE]<xsl:value-of select="title"/>[/TITLE]
  7.     <xsl:variable name="def" select="para/def" />
  8.     <xsl:call-template name="replace-string">
  9.         <xsl:with-param name="text" select="normalize-space(para)"/>
  10.         <xsl:with-param name="from" select="$def"/>
  11.         <xsl:with-param name="to" select="concat('[DEF]',$def,'[/DEF]')"/>
  12.     </xsl:call-template>
  13. </xsl:template>
  14.  
  15. <!--
  16.    Template para reemplazar cadenas.
  17.    [url]http://www.nectil.com/Public/ManualText.php?ID=2586&manualID=2547[/url]
  18.    -->
  19. <xsl:template name="replace-string">
  20.     <xsl:param name="text"/>
  21.     <xsl:param name="from"/>
  22.     <xsl:param name="to"/>
  23.  
  24.     <xsl:choose>
  25.       <xsl:when test="contains($text, $from)">
  26.           <xsl:variable name="before" select="substring-before($text, $from)"/>
  27.           <xsl:variable name="after" select="substring-after($text, $from)"/>
  28.           <xsl:variable name="prefix" select="concat($before, $to)"/>
  29.  
  30.           <xsl:value-of select="$before"/>
  31.           <xsl:value-of select="$to"/>
  32.           <xsl:call-template name="replace-string">
  33.             <xsl:with-param name="text" select="$after"/>
  34.             <xsl:with-param name="from" select="$from"/>
  35.               <xsl:with-param name="to" select="$to"/>
  36.           </xsl:call-template>
  37.         </xsl:when>
  38.         <xsl:otherwise>
  39.           <xsl:value-of select="$text"/>
  40.         </xsl:otherwise>
  41.     </xsl:choose>
  42.  
  43. </xsl:template>
  44. </xsl:stylesheet>

Y así es que consigo el objetivo buscado... quedo tranquilo por ahora. Ojalá a alguien más le sirva, cualquier comentario bienvenido.

__________________
٩(͡๏̯͡๏)۶
» Cómo hacer preguntas de manera inteligente «

"100 años después, la revolución no es con armas, es intelectual y digital"
  #5 (permalink)  
Antiguo 28/11/2008, 18:49
Avatar de jam1138
/** @package Moderador */
 
Fecha de Ingreso: julio-2004
Ubicación: sèveR led onieR lE
Mensajes: 9.368
Antigüedad: 20 años, 4 meses
Puntos: 102
Respuesta: Procesar etiqueta dentro de texto - XML -> XSL

Primero: se me pasó comentar que para XSL versión 2 hay una función replace() con la que no se tendría que recurrir a este template, por desgracia no pude hacer uso de esto.

Segundo: Justo ahora que lo envié , descubro hay un pequeño problema. Suponiendo tengo el siguiente XML:
Código xml:
Ver original
  1. <?xml version="1.0" ?>
  2. <seccion>
  3.     <title>Titulo</title>
  4.     <para>
  5.         Lorem <def>ipsum</def> postea ipsum complectitur eos in, mandamus disputationi
  6.         mediocritatem vix ei.
  7.     </para>
  8. </seccion>

cuando aplique mi plantilla obtendría el siguiente resultado (negritas donde ocurre el reemplazo):
Cita:
[TITLE]Titulo[/TITLE]
Lorem [DEF]ipsum[/DEF] postea [DEF]ipsum[/DEF] complectitur eos in, mandamus disputationi mediocritatem vix ei.
lo cual no sería lo correcto. Se trata solo de reemplazar el nodo; lo correcto debería de ser:
Cita:
[TITLE]Titulo[/TITLE]
Lorem [DEF]ipsum[/DEF] postea ipsum complectitur eos in, mandamus disputationi mediocritatem vix ei.
... para mi suerte, las probabilidades de que un error así ocurra son pocas (son palabras muy específicas), pero no deja de ser un error. Por ahora descanso, ya veré.

Abúr!
__________________
٩(͡๏̯͡๏)۶
» Cómo hacer preguntas de manera inteligente «

"100 años después, la revolución no es con armas, es intelectual y digital"
  #6 (permalink)  
Antiguo 29/11/2008, 02:50
Avatar de Ek-Balam  
Fecha de Ingreso: octubre-2008
Mensajes: 21
Antigüedad: 16 años, 1 mes
Puntos: 2
Respuesta: Procesar etiqueta dentro de texto - XML -> XSL

Saludos, Jam.

Yo te iba a proponer que usaras un DTD en el cual crearas un par de ENTITY para obtener directamente las tags [def] y [/def], pero leo que tú no tienes acceso al
archivo xml.

El ejemplo que hice es el siguiente (nombré los archivos como "p1.xml" y "p1.xsl", para hacer pruebas). El XML:


<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="p1.xsl"?>
<!DOCTYPE seccion[
<!ELEMENT seccion (title, para)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT para (#PCDATA)>
<!ENTITY XdefX "[def]">
<!ENTITY XxdefX "[/def]">
]>
<seccion>
<title>Titulo</title>
<para>Lorem &XdefX; ipsum &XxdefX; postea complectitur eos in,
mandamus disputationi mediocritatem vix ei.</para>
</seccion>


El XSL:



<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="seccion">
[TITLE]<xsl:value-of select="title"/>[/TITLE]
<xsl:value-of select="para" />
</xsl:template>
</xsl:stylesheet>


El resultado:

[TITLE]Titulo[/TITLE] Lorem [def] ipsum [/def] postea complectitur eos in, mandamus disputationi mediocritatem vix ei.


Como verás, con el DTD se hubieran creado directamente las tags para bbcode, pero si no puedes acceder al xml mi ayuda está de más.
Espero halles solución.
Buen día.
=0)
  #7 (permalink)  
Antiguo 30/11/2008, 20:19
Avatar de jam1138
/** @package Moderador */
 
Fecha de Ingreso: julio-2004
Ubicación: sèveR led onieR lE
Mensajes: 9.368
Antigüedad: 20 años, 4 meses
Puntos: 102
Respuesta: Procesar etiqueta dentro de texto - XML -> XSL

Gracias por la sugerencia Ek-Balam, entiendo lo que dices, pero no tengo acceso al XML... al menos no de primera mano. Son recursos que se extraen externamente, de vez en cuando han de hacer cambios externos, fuera de mi control, tengo que agarrarlos y transformarlos para trabajar con el resultado.

Pero bueno, ahora intenté esto:
Código xml:
Ver original
  1. <?xml version="1.0" ?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.    <xsl:output method="text" />
  4.  
  5.    <xsl:template match="/">
  6.        <xsl:for-each select="./*">
  7.            <xsl:apply-templates />
  8.        </xsl:for-each>
  9.    </xsl:template>
  10.  
  11.    <xsl:template match="title">
  12.        <xsl:text>[TITLE]</xsl:text>
  13.        <xsl:value-of select="." />
  14.        <xsl:text>[/TITLE]</xsl:text>
  15.    </xsl:template>
  16.  
  17.    <xsl:template match="def">
  18.        <xsl:text>[DEF]</xsl:text>
  19.        <xsl:value-of select="." />
  20.        <xsl:text>[/DEF]</xsl:text>
  21.    </xsl:template>
  22.  
  23. </xsl:stylesheet>
Trato directamente el nodo <def> sin tratar el <para> y funciona, pero ahora tengo problema con los espacios, pues la tabulación y el fin de línea se conservan y es algo que no debería. Este es (mas o menos) mi salida:
Código:
       [TITLE]Titulo[/TITLE]

               Lorem [DEF]ipsum[/DEF] postea ipsum complectitur eos in, mandamus disputationi
               mediocritatem vix ei.
El XML viene con saltos de línea si el texto pasa de 80 caracteres, pero yo necesito el texto corrido. Además, por la indentación de los nodos del XML igual se indenta el resultado (y hay saltos de línea extras), lo cuál necesito quitar. No puedo aplicar normalize-space() a para porque entonces, regreso al problema inicial (tratar <def> y colocarlo donde tiene que ir). Igual y se puede solucionar esto de otra manera; ¿ideas?.
__________________
٩(͡๏̯͡๏)۶
» Cómo hacer preguntas de manera inteligente «

"100 años después, la revolución no es con armas, es intelectual y digital"
  #8 (permalink)  
Antiguo 30/11/2008, 22:44
Avatar de Ek-Balam  
Fecha de Ingreso: octubre-2008
Mensajes: 21
Antigüedad: 16 años, 1 mes
Puntos: 2
Respuesta: Procesar etiqueta dentro de texto - XML -> XSL


Saludos de nuevo, Jam.

Estaba viendo en tu archivo .xsl un detallito. Quizá sea lo que te pueda
servir:

Elimina el "<xsl:output method="text" />" y el "<xsl:for-each select="./*">........</xsl:for-each>".
Y dentro del .xsl agrega una tabla.

El ejemplo sería así:



<?xml version="1.0" encoding="iso-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">

<table><tr><td>
<xsl:apply-templates />
</td></tr></table>

</xsl:template>

<xsl:template match="title">

<xsl:text>[TITLE]</xsl:text>
<xsl:value-of select="." />
<xsl:text>[/TITLE]</xsl:text>

</xsl:template>

<xsl:template match="def">
<xsl:text>[DEF]</xsl:text>
<xsl:value-of select="." />
<xsl:text>[/DEF]</xsl:text>

</xsl:template>

</xsl:stylesheet>


Probé tu código inicial con el IE7, FF y Ópera, y únicamente en el IE7 colocaba
el texto de corrido; mientras que en los otros 2, dejaba el salto de línea.
Ahora, yo he probado la modificación al xsl y en los 3 navegadores deja el texto
en una única línea.
Espero que esto sea lo que necesitas.
Buen día.
=0)
  #9 (permalink)  
Antiguo 01/12/2008, 00:52
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 10 meses
Puntos: 260
Sonrisa Respuesta: Procesar etiqueta dentro de texto - XML -> XSL

Hola,

Posiblemente funcione así:

Código xml:
Ver original
  1. <xsl:template match="/">
  2. <pre>
  3. <xsl:for-each select="seccion">[TITLE]<xsl:value-of select="normalize-space(title)"/> : [/TITLE]<xsl:for-each select="para">
  4.     <xsl:apply-templates select="."/>
  5.   </xsl:for-each>
  6. </xsl:for-each>
  7. </pre>
  8. </xsl:template>
  9.  
  10. <xsl:template match="para/def">[DEF]<xsl:value-of select="normalize-space(.)"/>[/DEF]</xsl:template>
  11. <xsl:template match="para/text()">[BLANK]<xsl:value-of select="normalize-space(.)"/>[/BLANK]</xsl:template>

Saludos,
  #10 (permalink)  
Antiguo 01/12/2008, 02:19
Avatar de jam1138
/** @package Moderador */
 
Fecha de Ingreso: julio-2004
Ubicación: sèveR led onieR lE
Mensajes: 9.368
Antigüedad: 20 años, 4 meses
Puntos: 102
Respuesta: Procesar etiqueta dentro de texto - XML -> XSL

Ek-Balam: Perdón por no mencionarlo, creí estaba implícito: La salida tendría que ser texto plano, no HTML. De lo que menciones, veo son cambios para tratarlo como HTML y verlo a través de un navegador, perdona las molestias.

HackmanC: ¡Gracias!. ¡Tan simple! . La manera de acceder a el texto del nodo es lo que necesitaba; ese 'match="para/text()"' ahí y aplico el normalize-space(.) al contenido. Gracias, diste en el clavo .

Entonces, paso el XSL final (ahora sí) con los siguientes cambios:
- Agrego <xsl:strip-space elements="*"/>. Esto elimina los espacios sobrantes de todos los elementos, osea, la tabulación y saltos de línea entre nodos. Estoy trabajando con texto plano , es necesario esto.
- Agrego el template para eliminar los saltos de línea (limitado a 80 caracteres) del nodo <para>, gracias al código de HackmanC.
- Agrego un salto de línea después de [/TITLE]. Nuevamente, al estar trabajando con texto plano, los saltos de línea son igual caracteres implicitos.

Código xml:
Ver original
  1. <?xml version="1.0" ?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.  
  4. <xsl:output method="text" />
  5. <xsl:strip-space elements="*" />
  6.  
  7. <xsl:template match="/">
  8.    <xsl:for-each select="./*">
  9.       <xsl:apply-templates />
  10.    </xsl:for-each>
  11. </xsl:template>
  12.  
  13. <xsl:template match="title">
  14.    <xsl:text>[TITLE]</xsl:text>
  15.    <xsl:value-of select="." />
  16.    <xsl:text>[/TITLE]
  17. </xsl:text>
  18. </xsl:template>
  19.  
  20. <xsl:template match="def">
  21.    <xsl:text>[DEF]</xsl:text>
  22.    <xsl:value-of select="." />
  23.    <xsl:text>[/DEF]</xsl:text>
  24. </xsl:template>
  25.  
  26. <xsl:template match="para/text()">
  27.    <xsl:value-of select="normalize-space(.)"/>
  28. </xsl:template>
  29.  
  30. </xsl:stylesheet>

Y voalá! . Muchas gracias a todos, creo ahora sí está solucionado, ojalá le sirva a alguien más.
__________________
٩(͡๏̯͡๏)۶
» Cómo hacer preguntas de manera inteligente «

"100 años después, la revolución no es con armas, es intelectual y digital"
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 22:59.