Una pregunta sobre XML, XSLT, docbook y namespace

A ver si hay alguno empollado en estas cosas (y no estoy mirando a ninguno ;-) ). Resulta que me he puesto con docbook y he intentado generar un xhtml a partir de xml de docbook con el procesador xsltproc. Además he intentado que fuese xhtml strict. Pero me queda salvar dos escollos:

  • las etiquetas
      aparecen con un atributo "type", que no sé cómo narices quitar, porque no veo ninguna forma de eliminarlas a través de, por ejemplo, un parámetro que le pasase a xsltproc. ¿Qué hay que hacer? ¿Buscarse luego la vida y quitarlas a manubrio o a través un xsl propio chapucero que copie todo excepto ese atributo?
    1. las tablas me están matando. Las escribo con la sintaxis de html y me aparecen siempre con un puñetero atributo xmlns="" en el xhtml resultante. He estado investigando dentro de mis limitaciones y creo que el problema está en que htmltbl.xsl hace un de los elementos propios de la tabla (,,, etc...). Si no ando descaminado, hace una copia exacta del nodo, incluido su namespace. Y, claro, como en mi .xml de docbook no especifico ninguno y el xhtml resultante empieza con un al llegar a la tabla se ve obligado a incluir un xmlns="". Mi pregunta ¿es esto correcto? Y sobre todo ¿hay alguna forma de solucionarlo?
Nunca me había dado por generar XHTML; pero he convertido el manual de ZonaSiete a XHTML y no he tenido los problemas que me dices de las tablas (no usamos
    afaik así que no he podido mirar).

    He llegado a algunas urls que a lo mejor te interesan (quizá las conozcas ya :P)

    Aquí hay algunos parámetros de la hoja de estilo:
    http://www.sagehill.net/docbookxsl/HtmlOutput.html

    Para generar xhtml:
    http://www.sagehill.net/docbookxsl/OtherOutputForms.html#GeneratingXhtml

    Y para generar strict:
    http://www.sagehill.net/docbookxsl/OtherOutputForms.html#StrictXhtmlValid

    Por otro lado, mira que tengas la última versión de las hojas de estilo, ya que por lo que he podido comprobar durante el desarrollo del manual de zonasiete cambian bastante entre versiones y algunos bugs tontos se arreglan.

    Salu2.Ferdy
Por partes:

el link sobre generar xhtml estricto ya lo había visto por encima. Sobre el problema de generar xhtml estricto y el "type" de dice:

ol does not take a type attribute.


Pero no el cómo. No es un problema que me preocupe demasiado, porque podría evitar escribir listas ordenadas y ya está.

El segundo me resulta más molesto. El caso es que me he puesto un ejemplo reducido a la mínima expresión:

<?xml version='1.0' encoding="iso-8859-1"?>
<!DOCTYPE article PUBLIC "-//OASIS/DTD DocBook V4.3//EN"
         "/usr/share/xml/docbook/schema/dtd/4.3/docbookx.dtd" >
<?xml-stylesheet type="text/xml"
          href="/usr/share/xml/docbook/stylesheet/nwalsh/xhtml/docbook.xsl"?>

<article lang="es">
        <title>Ejemplo</title>

        <section>
                <title>Primera seccion</title>

                <informaltable summary="Una tabla asquerosa">
                        <tbody>
                                <tr>
                                        <td>Nada de particular</td>
                                        <td>Otra cosa</td>
                                </tr>
                        </tbody>
                </informaltable>
        </section>
</article>


Y ahora genero el xhtml:
bash$ xsltproc ejemplo.xml > ejemplo.html

y el código html de la tabla es:

<table summary="Una tabla asquerosa">
     <tbody xmlns="">
        <tr>
               <td rowspan="1" colspan="1">Nada de particular</td>
               <td rowspan="1" colspan="1">Otra cosa</td>
        </tr>
      </tbody></table>


Me aparece el dichoso atributo del namespace en tbody. En table, no; porque en el caso particular de informaltable, no se genera con un en htmltbl.xsl, sino con una teiqueta puesta a pelo en formal.xsl. Pero en el resto de los elementos de la tabla. sí actúa el y desbarata el namespace. De hecho, si meto un elemento que no sea propio de una tabla (por ejemplo, meto la palabra "cosa" en un para generar un ), ocurre algo así:
<table summary="Una tabla asquerosa">
  <tbody xmlns="">
     <tr>
        <td rowspan="1" colspan="1">Nada de particular</td>
        <td rowspan="1" colspan="1">Otra <span
              xmlns="http://www.w3.org/1999/xhtml">cosa</span></td>
     </tr>
   </tbody>
</table>


Es decir, el elemento , que no se genera con el del resto de la tabla, vuelve a estar en el namespace adecuado. Aparece el atributo que refiere su namespace, porque su elemento contenedor no lo está.

Por cierto que en debian, la versión es la 1.66.noséqué. He probado a bajarme la última de sourceforge (1.68.1) y generarlo con ella y me sigue pasando lo mismo.

Una última cosa, uso porque me resultó sencillo localizar qué parte de las hojas xsl se encargaba de él. Con me sucede lo mismo excepto porque es en la propia etiqueta de xhtml en la que tengo el problema del namespace.

Bueno, esa era la penúltima cosa. La última es ¿tiene setido lo que dije? Es decir, como la hoja xsl hace un de los elementos de la tabla conserva el namespace de los elementos del documento .xml. En este caso, ninguno ("").

EDITO: No sé exactamente cómo generas tú el manual de zonasiete.org, ni cómo es porque no encuentro las fuentes docbook. Yo he probado a hackear un poco htmltbl.xsl y sustituir todos los por . No sé si me dará algún otro problema, pero ahora los namespace me van perfectamente. Incluso la variante del ejemplo en la que metía un phrase dentro.
Hola:

Pero no el cómo. No es un problema que me preocupe demasiado, porque podría evitar escribir listas ordenadas y ya está.


Suena a: "ol no toma tal atributo pero nosotros lo generamos, quítalo por tu cuenta.".



He visto tus ejemplos y ya entiendo qué problema tienes exactamente. Es muy probable que lo que dices del sea correcto; yo no lo se con certeza; pero parece coherente.

Por otro lado en la parte de generar XHTML estricto te recomienda crear un 'Costumization layer' en la que podrías hacer todos esos cambios y además dice algo sobre los namespaces:

If you don't include the namespace attribute in the stylesheet, then you will get namespace attributes in your XHTML output as an element switches out of the default XHTML namespace.


Suena similar a lo que te ocurre a ti ¿no?. Para los
    podrías crear un elemento "igual" en tu "costumization layer" y eliminar el código que genera el type por poner un ejemplo. Creo que sería la forma de solucionar todo el 'embolao'.

    Salu2.Ferdy
Ferdy escribió:Hola:

[...]

Por otro lado en la parte de generar XHTML estricto te recomienda crear un 'Costumization layer' en la que podrías hacer todos esos cambios y además dice algo sobre los namespaces:


Gracias, Ferdy. Ya había creado un xsl de personalización para algunas cosas que requerían muy pocas líneas y que me parecían un poco aberrantes en el xsl por efecto. Por ejemplo, que un elemento de docbook se convierta en un elemento de html (que para eso están) y no en un elemento con dos comillas puestas a pelo que lo rodean... ?:-/

Pero no creía que esto requiriese tanto... Me parece que voy a tener que modularizar la capa de personalización.

Gracias por tu tiempo.
Parece que el soporte es feote si... de hecho hay cosas de las XSL que son como bien has dicho aberrantes.

Si llegas a algo actualiza el hilo porque puede ser muy interesante.

Salu2.Ferdy
Ferdy escribió:Si llegas a algo actualiza el hilo porque puede ser muy interesante.


Pues me acabas de fastidiar bastante, porque yo pensaba chapucear un poco para salir del paso... ;-)

Veamos, tengo unos cuantos frentes abiertos:

a) Añadir un parámetro ("suppress.ol.type" para eliminar el parámetro "type" del elemento ol). Por ahora lo he hecho, pero sólo para los "ol" que genera . Sin embargo, creo que hay otros elementos de docbook que también se traducen a . Miraré cómo puedo generalizarlo.

b) Mejorar la personalización de la presentación con css. Me explico. Por lo que he podido comprobar , , , etc... se convierten en un cuya clase es el nombre del elemento docbook que le dio origen. Por ejemplo, se convierte en . Esto tiene un ligero contratiempo. Si por cualquier circunstancia, quiero que una lista tenga un aspecto diferente vía css, no hay medio humano de hacerlo (al menos a mí no se me ha ocurrido), porque el div ya tiene su atributo class, pillado. En realidad una sola lista sí tiene solución, porque se puede usar un parámetro "id". Pero un conjunto de listas, no; ya que en ese caso el recurso típico es ponerles a todas ellas una misma "class" y luego tratar a esa class en el css. La solución que se me ha ocurrido es añadirles a los elementos de docbook el atributo común "role" y que en vez de ser ignorado como hace ahora, se adjunte al valor de "class". Por ejemplo, ahora, genera y yo quiero que genere . De este modo las listas provenientes de itemized se pueden tratar en la hoja css con div[class*=itemizedlist] y las listas molonas con div.itemizedlist_listamolona. Ahora mismo sólo lo he solucionado para "itemizedlist", pero quiero buscarme una generalización para el resto de elementos.

c) Los problemas con las tablas y los espacios de nombres (esto creo que lo he solucionado)

d) Lo que surja... por ahora sólo he escrito un documento docbook.


Ya iré comentando cosillas conforme las vaya sacando.
Pues me acabas de fastidiar bastante, porque yo pensaba chapucear un poco para salir del paso... ;-)


Jaja, yo habría empezado a sed'ear desde el principio... seguro que eso era mucho más feo :P

b) me parece una cosa bastante interesante... pero realmente no se si será muy dificil o no.

Salu2.Ferdy
Ferdy escribió:Jaja, yo habría empezado a sed'ear desde el principio... seguro que eso era mucho más feo :P


Hombre, uno es chapuzas, pero no hasta tal punto.

b) me parece una cosa bastante interesante... pero realmente no se si será muy dificil o no.


En absoluto, es bastante sencillita. Basta con hacer un template y llamarlo desde todos los elementos de bloque que se quiera que actúen así. El problema es que hay que hacerlo con todos lo cual lo convierte en un poco tedioso.

Al final me he decidido a ir copiando la estructura de ficheros de las hojas xsl de walsh, de manera que si un template de walsh está en el fichero nosequé.xsl, en mi capa de personalización modular también esté en noséqué.xsl.

Por ahora, he cambiado el comportamiento de los elementos de bloque itemizedlist, orderedlist y blockquote. Cambiar el resto es trivial, aunque hay que hacerlo con un poco de paciencia. Además, he corregido otras cosas que no me gustaban como que docbook meta el atributo "id" en un elemento vacío en vez de hacerlo directamente en el "" (o en lo que toque).

Para los elementos de línea (, , etc... también he hecho algo similar), aunque me quedan bastantes.

Pego aquí un poco del código que he escrito para que se entienda y adjunto todo lo que he hecho hasta ahora. A ver si ahora que llega Pascua, hago todo lo que tengo en mente.

<xsl:template name="block.charseq">
    <xsl:param name="element_name" select="'div'" />
   <xsl:param name="supclass" />
   <xsl:param name="add.elementname" select="1" />
   <xsl:param name="content" />
   
   <xsl:element name="{$element_name}">
      <xsl:if test="@id">
         <xsl:attribute name="id">
            <xsl:value-of select="@id" />
         </xsl:attribute>
      </xsl:if>
      <xsl:if test="@dir">
         <xsl:attribute name="dir">
            <xsl:value-of select="@dir" />
         </xsl:attribute>
      </xsl:if>
      <xsl:if test="$element_name='div' or @role or $supclass!=''">
         <xsl:attribute name="class">
            <xsl:variable name="divclass">
               <xsl:if test="$element_name = 'div' and $add.elementname = 1">
                  <xsl:value-of select="local-name(.)" />
               </xsl:if>
            </xsl:variable>
            <xsl:variable name="role">
               <xsl:if test="@role and $para.propagates.style != 0">
                  <xsl:value-of select="@role" />
               </xsl:if>
            </xsl:variable>
               <xsl:value-of select="concat($divclass,$role,$supclass)" />
         </xsl:attribute>
      </xsl:if>
      <xsl:if test="@lang or @xml:lang">
         <xsl:call-template name="language.attribute"/>
      </xsl:if>
      <xsl:copy-of select="$content" />
   </xsl:element>
</xsl:template>

<xsl:template match="blockquote">
   <xsl:call-template name="block.charseq">
      <xsl:with-param name="element_name" select="'blockquote'" />
      <xsl:with-param name="content">
         <xsl:apply-templates select="child::*[local-name(.)!='attribution']"/>
         <xsl:apply-templates select="attribution" />
      </xsl:with-param>
   </xsl:call-template>
</xsl:template>


He puesto el ejemplo de cómo trato blockquote, pero el resto de elementos de bloque se tratarían de igual manera: se llama a la plantilla "block.charseq", se pasa el nombre del elemento xhtml por el cual se traducirá (si no se pasa ninguno se entiende que es el genérico "div") y se incluye en el parámetro "content" cuál es el tratamiento que se hace con el contenido del nodo.

Adjuntos

8 respuestas