2012-12-30 22 views
5

Ho un file XML e ho bisogno di convertirlo in XQuery. prendere in considerazione un semplice insieme di XML:Conversione da XML a CSV utilizzando XQuery

books[book] 
book[@isbn, title, descrption] 

esempio:

<books> 
    <book isbn="1590593049"> 
     <title>Extending Flash MX 2004</title> 
     <description> 
     Using javascript alongwith actionscript 3.0 and mxml.</description> 
    </book> 
    <book isbn="0132149184"> 
     <title>Java Software Solutions</title> 
     <description> 
      Complete book full of case studies on business solutions and design concepts while building mission critical 
      business applications. 
     </description> 
    </book> 

Come convertire in formato CSV utilizzando XQuery? Il CSV viene utilizzato da Microsoft excel,

in modo da essere delimitato da virgola (,) carattere e caratteri speciali devono essere sfuggiti.

risposta

4

A puro XPath 2.0 espressione:

for $b in /*/book 
    return 
     concat(escape-html-uri(string-join(($b/@isbn, 
              $b/title, 
              $b/description 
             ) 
              /normalize-space(), 
             ",") 
          ), 
      codepoints-to-string(10)) 

XSLT 2 - verifica base:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:sequence select= 
    "for $b in /*/book 
     return 
     concat(escape-html-uri(string-join(($b/@isbn, 
              $b/title, 
              $b/description 
              ) 
               /normalize-space(), 
              ',') 
           ), 
       codepoints-to-string(10))"/> 
</xsl:template> 
</xsl:stylesheet> 

Quando questa trasformazione è applicato sul documento XML fornito (corretta dal suo malformazioni):

<books> 
    <book isbn="1590593049"> 
     <title>Extending Flash MX 2004</title> 
     <description> 
     Using javascript alongwith actionscript 3.0 and mxml.</description> 
    </book> 
    <book isbn="0132149184"> 
     <title>Java Software Solutions</title> 
     <description> 
      Complete book full of case studies on business solutions and design concepts while building mission critical 
      business applications. 
     </description> 
    </book> 
</books> 

The Wanted, risultato corretto è prodotta:

1590593049,Extending Flash MX 2004,Using javascript alongwith actionscript 3.0 and mxml. 
0132149184,Java Software Solutions,Complete book full of case studies on business solutions and design concepts while building mission critical business applications. 

Aggiornamento:

In un commento il PO ha richiesto che ogni virgola avvolgere in-testo di un preventivo e che (dopo di che) ogni citazione viene sostituita da due virgolette e, infine, se il risultato contiene una citazione, deve essere racchiuso tra virgolette (singole).

Qui è una pura espressione XPath 2.0 che produce questo:

for $b in /*/book, 
    $q in codepoints-to-string(34), 
    $NL in codepoints-to-string(10), 
    $isbn in normalize-space(replace($b/@isbn, ',', concat($q,',',$q))), 
    $t in normalize-space(replace($b/title, ',', concat($q,',',$q))), 
    $d in normalize-space(replace($b/description, ',', concat($q,',',$q))), 
    $res in 
    escape-html-uri(string-join(($isbn,$t,$d), ',')), 
    $res2 in replace($res, $q, concat($q,$q)) 
    return 
    if(contains($res2, $q)) 
     then concat($q, $res2, $q, $NL) 
     else concat($res2, $NL) 

Quando questa espressione XPath viene valutata contro questo (ampliato con un nuovo test e minuscole) documento XML:

<books> 
    <book isbn="1590593049"> 
     <title>Extending Flash MX 2004</title> 
     <description> 
     Using javascript alongwith actionscript 3.0 and mxml.</description> 
    </book> 
    <book isbn="0132149184"> 
     <title>Java Software Solutions</title> 
     <description> 
      Complete book full of case studies on business solutions and design concepts while building mission critical 
      business applications. 
     </description> 
    </book> 
    <book isbn="XX1234567"> 
     <title>Quotes and comma</title> 
     <description> 
      Hello, World from "Ms-Excel" 
     </description> 
    </book> 
</books> 

il ricercato, il risultato corretto è prodotto:

1590593049,Extending Flash MX 2004,Using javascript alongwith actionscript 3.0 and mxml. 
0132149184,Java Software Solutions,Complete book full of case studies on business solutions and design concepts while building mission critical business applications. 
"XX1234567,Quotes and comma,Hello"","" World from ""Ms-Excel""" 
+0

ma se fosse XPath 2 puro non interpreterebbe ' ' come interruzione di riga – BeniBela

+0

@BeniBela, La tua domanda non è chiara - Ho aggiornato la mia risposta con un Trasformazione XSLT che utilizza la stessa espressione XPath. Nel caso in cui non si trattasse di un'espressione XPath legale, si sarebbe verificato un errore, ma la trasformazione funzionerà senza problemi –

+0

Bene, se lo includi in XSLT non è più * puro * XPath. Quindi il parser XML sostituisce & # xa. Se esegui semplicemente * pure * XPath senza XSLT ottieni: '1590593049, Estensione di Flash MX 2004, Utilizzo di javascript con actionscript 3.0 e mxml. 0132149184, Soluzioni software Java, libro completo completo di casi studio su soluzioni aziendali e concetti di progettazione mentre si costruiscono applicazioni aziendali mission-critical. 'nell'esempio – BeniBela

4

Assumendo che il XML è nella variabile $books è possibile creare un file CSV con ogni nodo libro su una nuova linea di utilizzo di questo:

declare function local:my-replace($input) { 
    for $i in $input 
    return '"' || replace($i, '"', '""') || '"' 
}; 
for $book in $books//book 
return string-join(local:my-replace(($book/@isbn, $book/title, $book/description)), ",") || '&#xa;' 

string-join concatena le diverse corde, la funzione locale my-replace sostituisce i valori in la sequenza in base alle vostre specifiche.

+0

lo snippet sopra riportato è ottimo in caso normale, ma in CSV i campi sono rappresentati da una virgola (,). Ora se un testo contiene una virgola, excel interpreterà quella virgola come una virgola separatrice, quando quella virgola era una parte del testo, ad esempio parte della cella descrittiva o della cella del titolo. Un approccio tipico è, per evitare le virgole racchiudendo virgolette doppie (") e sfuggire le virgolette aggiungendo virgolette prima delle doppie virgolette: Ciao, Mondo da" Ms-Excel "sarà:" Ciao, Mondo da "" Ms -Excel "" "Come fuggire in questo modo? Grazie per il tuo grande aiuto –

+0

Ho appena modificato la mia risposta per riflettere le specifiche che hai aggiunto.ho appena creato una funzione definita dall'utente my-replace, che aggiunge un" all'inizio e la fine di ogni elemento e sostituisce "with" ". – dirkk