2012-05-24 21 views
8

Tengo varios archivos DTD grandes. He usado trang para convertirlos en archivos XSD, por lo que podría usarlo fácilmente desde JAXB y otras utilidades. Sin embargo, el archivo XSD generado tiene todos los elementos declarados en el nivel superior. Significa que cualquier elemento podría ser un elemento raíz de un XML de entrada. Quiero especificar solo un elemento en particular.Convertir DTD en XSD con el elemento raíz (inicio) definido

Tener estos elementos raíz múltiples causa algunos problemas, p. xjc genera @XmlRootElement para todas las clases, así que necesito agregar más controles adicionales.

Según entiendo, necesito volver a escribir el XSD generado, moviendo <xs:element> s a <xs:complexType> s, cambiando element ref s en element type s y así sucesivamente, pero esto sería demasiado trabajo mono, y no hay forma de verificar si todo se hace correctamente.

¿Hay una manera más eficiente de hacer esto?

+0

+1 para una pregunta que tenga sentido, pero también deje en claro que la conversión de DTD a XSD siempre es solo aproximada. –

+0

@JirkaHanika Según tengo entendido, el XSD generado se aproxima mucho a una DTD. Excepto tal vez las definiciones DOCTYPE (aunque no es sorpresa) y algunas cosas del espacio de nombres. Además, algunas construcciones de DTD raras no pudieron transformarse en XSD de forma clara. El único problema al que me estoy enfrentando en este momento es que DTD no define la noción de elemento raíz. (RelaxNG lo define con '', pero es mal soportado, 'xjc' falló con él). – kan

+0

Sí, pero las cosas del espacio de nombres son un problema.Además, muchas construcciones que se llaman similares, significan cosas bastante diferentes. +1 a la primera respuesta porque no pretende ninguna semántica XSD. –

Respuesta

0

He usado la transformación simple XSLT para procesar el XSD generado. Funciona muy bien para mi 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> 

Detecta referencia definiciones de elementos y hacerlos comptexType s, el cambio de árbitros. Todos los elementos sin referencia se convierten en elementos de inicio.

0

Según lo que está describiendo e ignorando la "fidelidad" de la conversión, como se señala en algunos de los comentarios, solo estoy tratando con el hecho de que simplemente está buscando una forma automática de (lo que llamar) XML Schema Refactoring. Estoy asociado con QTAssistant, un producto que es para este tipo de trabajo, así que así es como lo haría ...

Una cosa que tienes que hacer a mano, sin importar qué, es descubrir y capturar la lista de elementos que desea ver como raíz (o no) ... y listo: presione un botón, o invoque una línea de comando, y sabrá con certeza si se genera un XSD válido.

Un motor de refactorización emplea un patrón de visitante que en su caso hace esencialmente lo que necesita: crea tipos globales cuando es necesario, elimina las definiciones de elementos globales no deseadas y reemplaza cualquier elemento refed con declaraciones en línea.

(Para cualquiera que lea esto que conoce grupos de sustitución, esta refactorización no reemplaza una referencia a un jefe de un grupo de sustitución, ya que estamos hablando de un XSD de un DTD, aquí no es un problema).

Esta simplicidad, y el hecho de que es repetible y confiable, serían las principales ventajas de utilizar una herramienta de refactorización especializada; otra ventaja: también puede reasignar espacios de nombres xml, de todos modos usted quiere ...

Si está interesado en más detalles, hágamelo saber y actualizaré esta publicación con una pequeña muestra y algunas ilustraciones.