Foros del Web

Foros del Web (http://www.forosdelweb.com/)
-   Programación General (http://www.forosdelweb.com/f14/)
-   -   Procesar etiqueta dentro de texto - XML -> XSL [Solucionado] (http://www.forosdelweb.com/f14/procesar-etiqueta-dentro-texto-xml-xsl-solucionado-648843/)

jam1138 27/11/2008 17:14

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é :-). :adios:

monoswim 28/11/2008 05:17

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...

:adios:

jam1138 28/11/2008 12:39

Respuesta: Procesar etiqueta dentro de texto - XML -> XSL
 
Cita:

Iniciado por monoswim (Mensaje 2683385)
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.

:adios:

jam1138 28/11/2008 18:40

Respuesta: Procesar etiqueta dentro de texto - XML -> XSL
 
Uf, uf, uf y recontra uf! :neurotico:

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.

:adios:

jam1138 28/11/2008 18:49

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! :adios:

Ek-Balam 29/11/2008 02:50

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)

jam1138 30/11/2008 20:19

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?.

Ek-Balam 30/11/2008 22:44

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)

HackmanC 01/12/2008 00:52

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,

jam1138 01/12/2008 02:19

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! :-P. 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. :adios:


La zona horaria es GMT -6. Ahora son las 10:56.

Desarrollado por vBulletin® Versión 3.8.7
Derechos de Autor ©2000 - 2026, Jelsoft Enterprises Ltd.