2010-05-17 14 views
6

me gustaría convertir XML en CSV con un XSLT, pero cuando se aplica el XSL del hilo para titulado XML To CSV XSLT contra mi entrada:XML a CSV mediante XSLT ayuda

 
<WhoisRecord> 
    <DomainName>127.0.0.1</DomainName> 
    <RegistryData> 
    <AbuseContact> 
     <Email>[email protected]</Email> 
     <Name>Internet Corporation for Assigned Names and Number</Name> 
     <Phone>+1-310-301-5820</Phone> 
    </AbuseContact> 
    <AdministrativeContact i:nil="true"/> 
    <BillingContact i:nil="true"/> 
    <CreatedDate/> 
    <RawText>...</RawText> 
    <Registrant> 
     <Address>4676 Admiralty Way, Suite 330</Address> 
     <City>Marina del Rey</City> 
     <Country>US</Country> 
     <Name>Internet Assigned Numbers Authority</Name> 
     <PostalCode>90292-6695</PostalCode> 
     <StateProv>CA</StateProv> 
    </Registrant> 
    <TechnicalContact> 
     <Email>[email protected]</Email> 
     <Name>Internet Corporation for Assigned Names and Number</Name> 
     <Phone>+1-310-301-5820</Phone> 
    </TechnicalContact> 
    <UpdatedDate>2010-04-14</UpdatedDate> 
    <ZoneContact i:nil="true"/> 
    </RegistryData> 
</WhoisRecord> 

termino con:

[email protected] Corporation for Assigned Names and Number+1-310-301-5820, 
    , 
    , 
    , 
    ...,  
    4676 Admiralty Way, Suite 330Marina del ReyUSInternet Assigned Numbers Authority90292-6695CA,  
    [email protected] Corporation for Assigned Names and Number+1-310-301-5820,  
    2010-04-14, 

Mi problema es que, la transformación resultante falta nodos (como el elemento de Dominio que contiene la dirección IP) y algunos nodos secundarios se concatenan sin comas (como los hijos de AbuseContact).

Me gustaría ver todos los resultados XML en formato CSV, y cadenas como: "[email protected] Corporación de Internet para Nombres Asignados y Número + 1-310-301-5820", delimitada por comas.

Mi XSL está bastante oxidado. Tu ayuda es apreciada. :)

Aquí está el XSL que estoy usando:

 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text" encoding="iso-8859-1"/> 

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

<xsl:template match="/*/child::*"> 
    <xsl:for-each select="child::*"> 
    <xsl:if test="position() != last()"><xsl:value-of select="normalize-space(.)"/>, </xsl:if> 
    <xsl:if test="position() = last()"><xsl:value-of select="normalize-space(.)"/><xsl:text>
</xsl:text> 
    </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 
+1

Buena pregunta (+1). Vea mi respuesta para una solución simple. :) –

Respuesta

3

Este simple transformación produce el resultado deseado:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 
<xsl:strip-space elements="*"/> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="//text()"/> 
    </xsl:template> 

    <xsl:template match="text()"> 
     <xsl:copy-of select="."/> 
     <xsl:if test="not(position()=last())">,</xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

hacer la nota el uso de:

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

para descartar los nodos de texto de espacio en blanco de sólo.

Actualización: AJ planteó el problema de que los resultados deberían agruparse en recirds/tuplas por línea. No se define en la pregunta qué debe ser exactamente un registro/tupla. Por lo tanto, la solución actual resuelve los dos problemas de los nodos de texto de espacio en blanco y de las comas que faltan, pero no apunta a generar la salida en registros/tuplas.

+0

¿No requiere CSV una nueva línea para separar un conjunto/tupla de registros? –

+2

No está claro, a partir de la pregunta, qué constituye una tupla de registros; esto tiene significado en el mundo de las bases de datos relacionales, pero para un árbol debe definirse explícitamente. También edité mi respuesta para reflejar su comentario. –

+0

¡Gracias chicos! Me gustaría un conjunto/tupla de registros. ¿Qué tan difícil podría ser? También me gustaría poder aplicar el XSL a documentos XML de estructura similar; se prefieren las soluciones que no hacen referencia a los elementos por su nombre. Gracias de nuevo. :) –

0

Creo que necesita una solución recursiva para abordar este problema. Entonces, necesitarías algo que siga sumergiéndose en el árbol hasta que llegue a un nodo de texto(). Si ese nodo de texto() es realmente un elemento secundario del último nodo, coloca una nueva línea. De lo contrario, solo pone el valor con una coma.

Si el nodo no tiene un nodo de texto() como su hijo, entonces comienza recursivamente a cavar en ese árbol.

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

<xsl:template name="rec">   
    <xsl:param name="node"/>   
    <xsl:for-each select="child::*"> 
     <xsl:choose> 
      <xsl:when test="child::text()"> 
       <xsl:choose>       
        <xsl:when test="local-name(.) != 'UpdatedDate'">"<xsl:value-of select="normalize-space(.)"/>", </xsl:when> 
        <xsl:otherwise>"<xsl:value-of select="normalize-space(.)"/>" <xsl:text>&#xD;</xsl:text></xsl:otherwise> 
       </xsl:choose>      
      </xsl:when> 
      <xsl:when test="child::node()"> 
       <xsl:call-template name="rec"> 
        <xsl:with-param name="node" select="child::node()"/> 
       </xsl:call-template>      
      </xsl:when> 
     </xsl:choose> 

    </xsl:for-each> 
</xsl:template> 

Esto no es a toda prueba, sino que produjo este resultado en mi final con sajona:

"127.0.0.1", "[email protected]", "Internet Corporation for Assigned Names and Number", "+1-310-301-5820", "...", "4676 Admiralty Way, Suite 330", "Marina del Rey", "US", "Internet Assigned Numbers Authority", "90292-6695", "CA", "[email protected]", "Internet Corporation for Assigned Names and Number", "+1-310-301-5820", "2010-04-14" 

Espero que esto ayude.

+0

¿Por qué mi respuesta fue rechazada? Un comentario al respecto hubiera sido útil. Soy nuevo en XSLT. –

+1

Probablemente porque no hay una recursión o bucle explícito necesario para moverse a lo largo del eje secundario. – Tomalak

Cuestiones relacionadas