2008-09-17 22 views
6

Tiene que haber una forma genérica para transformar algunas XML jerárquico tales como:aplanar XML a una tabla HTML

<element1 A="AValue" B="BValue"> 
    <element2 C="DValue" D="CValue"> 
     <element3 E="EValue1" F="FValue1"/> 
     <element3 E="EValue2" F="FValue2"/> 
    </element2> 
    ... 
</element1> 

en el XML aplanada (html) recogiendo los atributos seleccionados a lo largo del camino y proporcionando diferentes etiquetas para los atributos que se convierten en encabezados de columna.

<table> 
    <tr> 
    <th>A_Label</th> 
    <th>D_Label</th> 
    <th>E_Label</th> 
    <th>F_Label</th> 
    </tr> 
    <tr> 
    <td>AValue</td> 
    <td>DValue</td> 
    <td>EValue1</td> 
    <td>FValue1</td> 
    </tr> 
    <tr> 
    <td>AValue</td> 
    <td>DValue</td> 
    <td>EValue2</td> 
    <td>FValue2</td> 
    </tr> 
<table> 

OK, así que no existe una solución genérica debido a la nueva etiqueta del atributo, pero entiendes lo que quiero decir. Empecé con todas las cosas de XSLT/XPATH, así que lo resolveré a tiempo, pero cualquier pista sería útil.

Respuesta

5

No estoy 100% seguro de lo que está tratando de hacer pero esta solución puede funcionar si su element1, element2 y element3 están anidados constantemente.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <table> 
      <xsl:apply-templates select="//element3"></xsl:apply-templates> 
     </table> 
    </xsl:template> 

    <xsl:template match="element3"> 
     <tr> 
      <td><xsl:value-of select="../../@A"/></td> 
      <td><xsl:value-of select="../../@B"/></td> 
      <td><xsl:value-of select="../@C"/></td> 
      <td><xsl:value-of select="../@D"/></td> 
      <td><xsl:value-of select="@E"/></td> 
      <td><xsl:value-of select="@F"/></td> 
     </tr> 
     <xsl:apply-templates select="*"></xsl:apply-templates> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Gracias Darrel. Funciona magníficamente. –

+0

Buena muestra. ¡Gracias! – chrismead

0

Ya tenemos un programa Pro * C leyendo de una base de datos Oracle, llama a un script perl que a su vez ejecuta algo de Java para extraer datos en formato XML de la base de datos antes mencionada para llamar a un archivo por lotes para ejecutar vbscript. archivo a otro servidor. Realmente estaba esperando algo en Fortran.

+0

menos mal ... hasta que llegué a la parte FORTRAN pensé que eras seria allí por un segundo – davr

0

La pregunta original necesita ser aclarado:

  • ¿Qué ocurre con BValue y cValue en la pregunta original? ¿Hay alguna razón por la cual no deberían ser parte de la estructura aplanada?
  • ¿Todos los elementos del documento XML tienen 2 atributos o es completamente arbitrario?
  • ¿Hay solo 3 tipos de elementos y siempre están anidados como se muestra en el ejemplo?
  • ¿Puede su elemento1 repetirse o este es el elemento raíz de su documento?

En XSLT es posible escribir transformadores muy genérica, pero es a menudo mucho más fácil de escribir una hoja de estilo para transformar un documento cuando se puede tomar ningún tipo de restricciones conocidas en cuenta.

0

He utilizado una versión ampliada de la plantilla siguiente para aplanar XML estructurado. Advertencia: Hubo algún código específico de un caso en la versión original (de hecho convirtió el XML en CSV) que acabo de quitar y no probé esta versión.

La forma básica en que funciona debe ser clara: imprime todo lo que no tiene nodo secundario y de lo contrario recurre a la plantilla en el nodo() que sí tiene elementos secundarios. No creo que maneje los atributos y comentarios correctamente como lo está ahora, pero eso no debería ser difícil de arreglar.

<?xml version="1.0" encoding="UTF-8"?> 

<!-- XSL template to flatten structured XML, before converting to CSV. --> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/> 

    <xsl:strip-space elements="*" /> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="//yourElementsToFlatten"/> 
    </xsl:template> 

    <xsl:template match="//yourElementsToFlatten"> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
     <xsl:choose> 
      <!-- If the element has multiple childs, call this template 
       on its children to flatten it--> 
      <xsl:when test="count(child::*) > 0"> 
       <xsl:apply-templates select="@*|node()"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:copy> 
        <xsl:value-of select="text()" /> 
       </xsl:copy> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 
1

Necesitaba un XSLT similar pero con profundidad desconocida, así es como lo hice.

En primer lugar, añadir una envoltura para el modo resultante tabla HTML/def lista y llamar a la plantilla = "vomitar" para aplanar nuestro árbol XML:

<xsl:element name="div"> 
    <xsl:attribute name="class" select="puke" /> 
    <xsl:apply-templates select="$notice" mode="puke" /> 
</xsl:element> 

Aquí coinciden con cada nodo para mostrar su contenido (por ejemplo, texto()) y sus atributos. Hacemos esto recursivamente Usé dl/dt/dd porque mi árbol fuente era un árbol complejo que no se puede aplanar como a.

<!-- @description: 
    Display all field from the notice so the customer can tell what he want 
--> 
<xsl:template match="node()" mode="puke"> 
<xsl:message> 
    puking : <xsl:value-of select="local-name(.)" /> 
</xsl:message> 
    <xsl:element name="dl"> 
     <xsl:element name="dt"> 
      <xsl:attribute name="class">tagName</xsl:attribute> 
      <xsl:value-of select="local-name(.)" /> 
     </xsl:element> 
     <xsl:element name="dd"> 
      <xsl:attribute name="class">tagText</xsl:attribute> 
      <xsl:value-of select="text()" /></xsl:element> 
     <xsl:element name="dl"> 
      <xsl:attribute name="class">attr</xsl:attribute> 
      <!-- display attribute --> 
      <xsl:apply-templates select="@*" /> 
     </xsl:element> 
    </xsl:element> 
    <!-- recursive call on node() --> 
    <xsl:apply-templates select="./*" mode="puke" />  
</xsl:template> 

Empareje el atributo de un nodo determinado y muéstrelo.

El CSS utilizar en formatear el HTML resultante:

<style> 
.puke { 
    background-color: #BDD6DE; 
    clear: both; 
} 
.tagName, .attrName { 
    float: left; 
} 
.tagText, .attrText { 
    clear: right; 
} 
</style>