2011-04-19 20 views
6

Necesito crear un esquema XSD basado en un archivo XML. ¿Hay algún módulo de Perl que pueda hacer esto?¿Cómo puedo crear un esquema a partir de un documento XML de ejemplo en Perl?

+4

relacionada a esta pregunta: para una herramienta de Java, consulte [Trang ] (http://www.thaiopensource.com/relaxng/trang-manual.html#xsd-output). Para la dirección inversa, vea [XML-Pastor] (http://p3rl.org/XML::Pastor). – daxim

+1

Un archivo XSD generado por un archivo XML no tiene mucho valor. Solo se puede modelar la estructura del archivo XML. El archivo XSD no incluirá ninguna restricción, ya que no puede adivinar que 2011 es un año y, por lo tanto, no es posible definir ninguna restricción. ¿Un archivo XSD que modele solo la estructura satisfaga sus requisitos? – ceving

Respuesta

4

Puede crear el XSD mediante una transformación XSL utilizando cualquier procesador XSLT. Ver XML::XSLT

Un archivo XSD contiene dos tipos de elementos: simple y complejo. Todos los nodos de hoja deben traducirse en elementos de tipo simple y los demás deben traducirse a tipos complejos. Los nodos de hojas son nodos sin ningún descendiente. El XPath correspondiente es //*[not(descendant::element())]. La siguiente XSLT implementa este approch:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="/"> 
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       elementFormDefault="qualified" 
       attributeFormDefault="unqualified"> 
     <xsl:for-each select="//*[not(descendant::element())]"> 
     <xsl:element name="xs:element"> 
      <xsl:attribute name="name"> 
      <xsl:value-of select="name()"/> 
      </xsl:attribute> 
      <xs:simpleType> 
      <xs:restriction base="xs:string"/> 
      </xs:simpleType> 
     </xsl:element> 
     </xsl:for-each> 
     <xsl:for-each select="//*[descendant::element()]"> 
     <xsl:element name="xs:element"> 
      <xsl:attribute name="name"> 
      <xsl:value-of select="name()"/> 
      </xsl:attribute> 
      <xs:complexType> 
      <xs:sequence> 
       <xsl:for-each select="child::*"> 
       <xsl:element name="xs:element"> 
        <xsl:attribute name="ref"> 
        <xsl:value-of select="name()"/> 
        </xsl:attribute> 
       </xsl:element> 
       </xsl:for-each> 
      </xs:sequence> 
      </xs:complexType> 
     </xsl:element> 
     </xsl:for-each> 
    </xs:schema> 
    </xsl:template> 
</xsl:stylesheet> 

el siguiente ejemplo:

<?xml version="1.0" encoding="UTF-8"?> 
<person> 
    <firstname>Peter</firstname> 
    <lastname>Pan</lastname> 
    <born> 
    <year>1904</year> 
    <month>12</month> 
    <day>27</day> 
    </born> 
</person> 

producirá el siguiente esquema:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      elementFormDefault="qualified" 
      attributeFormDefault="unqualified"> 
    <xs:element name="firstname"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="lastname"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="year"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="month"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="day"> 
    <xs:simpleType> 
     <xs:restriction base="xs:string"/> 
    </xs:simpleType> 
    </xs:element> 
    <xs:element name="person"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element ref="firstname"/> 
     <xs:element ref="lastname"/> 
     <xs:element ref="born"/> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
    <xs:element name="born"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element ref="year"/> 
     <xs:element ref="month"/> 
     <xs:element ref="day"/> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 
+1

¡Funciona para mí! Como en realidad no está utilizando ninguna de las características de XSLT 2.0, podría ir a la versión 1.0 de mayor extensión. Solo tendrías que cambiar 'descenddant :: element()' por 'descenddant :: *'. – Lumi

+0

Consulte también [XML :: LibXSLT] (http://search.cpan.org/~pajas/XML-LibXSLT/), que es su mejor opción en Perl al hacer XSLT. – Lumi

Cuestiones relacionadas