XSD到FBS的XSLT转换(Flatbuffers)

时间:2017-03-24 11:57:31

标签: xslt xsd flatbuffers

我有许多用xsd编写的XML-schematas来定义xml文档的结构。现在我想用flatbuffers替换格式。在查看fbs格式时,可以使用XSLT将XSD架构定义自动转换为FBS文件。 因为可能有其他人有同样的问题我在这里问,是否已经有一些方法来解决XSD Schematas到FBS的自动转换。

XSD-Schema示例:

<xs:complexType name="Configuration">
  <xs:sequence>
    <xs:element name="MandatoryDetail" 
                type="ComplexConfigDetail" 
                minOccurs="1" 
                maxOccurs="1"/>
    <xs:element name="OptionalDetail" 
                type="ComplexConfigDetail" 
                minOccurs="0" 
                maxOccurs="1"/>
    <xs:element name="UnboundedDetail" 
                type="ComplexConfigDetail" 
                minOccurs="0" 
                maxOccurs="unbounded"/>
  </xs:sequence>
  <xs:attribute name="MandatoryInt" 
                use="required" 
                type="xs:unsignedInt"/>
  <xs:attribute name="OptionalInt" 
                use="optional" 
                type="xs:unsignedInt"/>
</xs:complexType>

<xs:complexType name="ComplexConfigDetail">
  <xs:sequence maxOccurs="1">
  <xs:element name="Frame" 
              type="xs:int" 
              minOccurs="0" 
              maxOccurs="1"/>
  </xs:sequence>
</xs:complexType>

预期的FBS架构:

namespace http_www_demo_com_config

table ComplexConfigDetail {
    DetailElement : int;
}

table Configuration {
    MandatoryInt : uint (required);
    OptionalInt : uint;
    MandatoryDetail : ComplexConfigDetail (required);
    OptionalDetail : ComplexConfigDetail;
    UnboundedDetail : [ComplexConfigDetail];
}

是否有可用的转换,例如XSLT。

修改 感谢Dan我将他的XSLT扩展到了这个也处理xs:extensions(继承)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                version="1.0">

  <xsl:output method="text" omit-xml-declaration="yes" />

  <xsl:template match="/xs:schema">namespace http_www_demo_com_config;
    <xsl:apply-templates select="//xs:simpleType" />
    <xsl:apply-templates select="//xs:complexType" />
</xsl:template>

  <xsl:template match="xs:simpleType[xs:restriction/@base='xs:string' and count(xs:restriction/xs:enumeration) > 0]">
enum <xsl:value-of select="@name"/> : byte {
  <xsl:for-each select="xs:restriction/xs:enumeration" >
    <xsl:value-of select="@value"/>
      <xsl:if test="position() != last()">
        <xsl:text>,
  </xsl:text>
      </xsl:if>
    </xsl:for-each>
 }</xsl:template>

<xsl:template name="complexTypeMatch" match="xs:complexType">
table <xsl:value-of select="@name" /> {
<xsl:apply-templates select="xs:complexContent" />
  <xsl:apply-templates select="xs:sequence/xs:element" />
  <xsl:apply-templates select="xs:attribute" />  }
</xsl:template>

  <xsl:template match="xs:complexContent">
    <xsl:apply-templates  select="xs:extension"/>
  </xsl:template>

<xsl:template name="extensionType" match="xs:extension">
<xsl:apply-templates select="//xs:complexType[@name=current()/@base]/xs:complexContent" />
<xsl:apply-templates select="//xs:complexType[@name=current()/@base]/xs:sequence/xs:element"/>
<xsl:apply-templates select="//xs:complexType[@name=current()/@base]/xs:attribute"/>
</xsl:template>

<xsl:template match="xs:element | xs:attribute">
  <xsl:text>  </xsl:text>
  <xsl:value-of select="@name" /> : <xsl:if test="@maxOccurs != 1">[</xsl:if>
  <xsl:call-template name="typeTransformer">
    <xsl:with-param name="type" select="@type" />
  </xsl:call-template>
<xsl:if test="@maxOccurs != 1">]</xsl:if>
<xsl:if test="@minOccurs > 0"> (required)</xsl:if>
<xsl:text>;&#13;&#10;</xsl:text>
</xsl:template>

<xsl:template name="typeTransformer">
  <xsl:param name="type" />
  <xsl:choose>
      <xsl:when test="$type = 'xs:unsignedInt'"><xsl:text>uint</xsl:text></xsl:when>
      <xsl:when test="$type = 'xs:unsignedByte'"><xsl:text>ubyte</xsl:text></xsl:when>
      <xsl:when test="starts-with($type, 'xs:')"><xsl:value-of select="substring-after($type, 'xs:')" /></xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="$type" />
  </xsl:otherwise>
</xsl:choose>

</xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

写一个不应该非常复杂,例如:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
  <xsl:output method="text" omit-xml-declaration="yes" />
  <xsl:template match="/xs:schema">
namespace http_www_demo_com_config
    <xsl:apply-templates />
  </xsl:template>
  <xsl:template match="xs:complexType">
table <xsl:value-of select="@name" /> {
    <xsl:apply-templates />
}
  </xsl:template>

  <xsl:template match="xs:element | xs:attribute">
    <xsl:value-of select="@name" /> : 
    <xsl:if test="@maxOccurs != 1">[</xsl:if>
    <xsl:call-template name="typeTransformer">
      <xsl:with-param name="type" select="@type" />
    </xsl:call-template>
    <xsl:if test="@maxOccurs != 1">]</xsl:if>
    <xsl:if test="@minOccurs > 0"> (required)</xsl:if>
    <xsl:text>&#13;&#10;</xsl:text>
  </xsl:template>

  <xsl:template name="typeTransformer">
    <xsl:param name="type" />
    <xsl:choose>
      <xsl:when test="$type = 'xs:unsignedInt'">
         <xsl:text>uint</xsl:text>
      </xsl:when>
      <xsl:when test="starts-with($type, 'xs:')">
         <xsl:value-of select="substring-after($type, 'xs:')" />
      </xsl:when>
      <xsl:otherwise>
         <xsl:value-of select="$type" />  
      </xsl:otherwise>
    </xsl:choose>

  </xsl:template>
</xsl:stylesheet>

只需展开choice即可转换您未能正确排列的其他特定属性值。