2012-05-24 17 views
8

Ho diversi file DTD di grandi dimensioni. Ho usato trang per convertirli in file XSD, quindi ho potuto facilmente usarlo da JAXB e altre utilità. Tuttavia, il file XSD generato ha tutti gli elementi dichiarati al livello più alto. Significa che qualsiasi elemento potrebbe essere l'elemento radice di un XML di input. Voglio specificare solo un particolare elemento.Converti DTD in XSD con elemento radice definito (iniziale)

Avere questi elementi radice multipli causa alcuni problemi, ad es. xjc genera @XmlRootElement per tutte le classi, quindi ho bisogno di aggiungere ulteriori controlli aggiuntivi.

A quanto ho capito, ho bisogno di riscrivere il XSD generato, spostando <xs:element> s per <xs:complexType> s, cambiando element ref s in element type s e così via, ma questo sarebbe troppo lavoro scimmia, e non c'è modo di verificare se tutto fatto correttamente.

Esiste un modo più efficiente per farlo?

+0

+1 per una domanda che ha senso, ma chiariamo anche che la conversione da DTD a XSD è sempre solo approssimativa. –

+0

@JirkaHanika Come ho capito, l'XSD generato si avvicina molto bene a un DTD. Tranne forse le definizioni DOCTYPE (nessuna sorpresa però) e alcune cose del namespace. Inoltre alcuni costrutti DTD strani non possono essere trasformati in XSD in modo ordinato. L'unico problema che sto affrontando al momento, che DTD non definisce nozione di elemento radice. (RelaxNG lo definisce con '', ma è mal supportato, 'xjc' non è riuscito con esso). – kan

+0

Sì, ma lo spazio dei nomi è un problema.Inoltre molti costrutti denominati simili, significano cose piuttosto diverse. +1 alla prima risposta perché non pretende alcuna semantica XSD. –

risposta

0

Ho usato la trasformazione XSLT semplice per elaborare l'XSD generato. Funziona bene per il mio caso:

<?xml version="1.0"?> 

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     > 
    <xsl:template match="@*|node()|comment()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()|comment()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="xs:element/@ref"/> 
    <xsl:template match="xs:element[@ref]"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:attribute name="type"><xsl:value-of select="@ref"/></xsl:attribute> 
      <xsl:attribute name="name"><xsl:value-of select="@ref"/></xsl:attribute> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="xs:element[@name = //xs:element/@ref and xs:complexType]"> 
     <xs:complexType name="{@name}"> 
      <xsl:apply-templates select="xs:complexType/node()"/> 
     </xs:complexType> 
    </xsl:template> 
    <xsl:template match="xs:element[@name = //xs:element/@ref and @type]"> 
     <xsl:choose> 
      <xsl:when test="//xs:complexType[@name = current()/@type]"> 
       <xs:complexType name="{@name}"> 
        <xs:complexContent> 
         <xs:extension base="{@type}"/> 
        </xs:complexContent> 
       </xs:complexType> 
      </xsl:when> 
      <xsl:otherwise> 
       <xs:simpleType name="{@name}"> 
        <xs:restriction base="{@type}"/> 
       </xs:simpleType> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

Si rileva riferimento definizioni degli elementi e renderli comptexType s, cambiando rif. Tutti gli elementi non referenziati diventano elementi di partenza.

0

Da quello che stai descrivendo, e ignorando la "fedeltà" della conversione come sottolineato in alcuni dei commenti, io sono solo che fare con il fatto che si sta semplicemente cercando qualche modo automatica di (quello che ho chiamata) Refactoring schema XML. Sono associato a QTAssistant, un prodotto che è pensato per questo tipo di lavoro, quindi questo è come lo farei ...

Una cosa che devi fare a mano, non importa cosa, è capire e catturare l'elenco di elementi che desideri vedere come root (o meno) ... e il gioco è fatto: premi un pulsante o invoca una riga di comando e saprai con certezza se viene generato un XSD valido.

Un motore di refactoring utilizza uno schema di visitatore che nel tuo caso fa essenzialmente ciò di cui hai bisogno: crea tipi globali laddove necessario, rimuove le definizioni di elementi globali indesiderate e sostituisce qualsiasi elemento refed con dichiarazioni in linea.

(Per chi legge questo che conosce i gruppi di sostituzione, questo refactoring non sostituisce un riferimento a un capo di un gruppo di sostituzione, poiché stiamo parlando di un XSD da un DTD, questo non è un problema qui).

Questa semplicità e il fatto che sia ripetibile e affidabile sono i principali vantaggi dell'utilizzo di uno strumento di refactoring specializzato; un altro vantaggio: può anche riassegnare spazi dei nomi xml, in ogni caso ...

Se sei interessato a maggiori dettagli, fammi sapere e aggiornerò questo post con un piccolo esempio e alcune illustrazioni.