2012-09-18 153 views
2

我需要将源模式定义的所有Float和Double数据类型转换为十进制数据类型。XML数据类型转换

我们有一个现有的XSLT,它从第三方获取XML文档并将其转换为XML结构,然后传递给我们的4GL DB应用程序。原生4GL接口的好处在于它可以将入站XML转换为原生数据集结构。简而言之,它将Float和Double数据类型映射到字符数据类型。

在XSLT中是否有一种方法来标识浮点/双精度数据类型的元素并将其转换为小数。我认为这可能是XSLT之前的主要步骤,然后将输出传递到主XSLT。

示例方案:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="ttPTManifest"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="JobCode"/> 
       <xs:element ref="EstimateHours"/> 
       <xs:element ref="ActualHours"/> 
       <xs:element ref="Density"/> 
       <xs:element ref="NettLitres"/> 
       <xs:element ref="QuitOutLitres"/> 
       <xs:element ref="QuitInLitres"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="QuitOutLitres" type="xs:double"/> 
    <xs:element name="QuitInLitres" type="xs:float"/> 
    <xs:element name="PTManifestSonicIn"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="ttPTManifest"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="JobCode" type="xs:string"/> 
    <xs:element name="NettLitres" type="xs:double"/> 
    <xs:element name="EstimateHours" type="xs:float"/> 
    <xs:element name="Density" type="xs:decimal"/> 
    <xs:element name="ActualHours" type="xs:float"/> 
</xs:schema> 

示例XML数据:

<?xml version="1.0"?> 
<PTManifestSonicIn xsi:noNamespaceSchemaLocation="SampleIn.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <ttPTManifest> 
     <JobCode>000123</JobCode> 
     <EstimateHours>3.14159E3</EstimateHours> 
     <ActualHours>3.14159E3</ActualHours> 
     <Density>123.456</Density> 
     <NettLitres>3.14159265358979E3</NettLitres> 
     <QuitOutLitres>3.14159265358979E3</QuitOutLitres> 
     <QuitInLitres>3.14159E3</QuitInLitres> 
    </ttPTManifest> 
</PTManifestSonicIn> 

Rerquired架构日期:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="ttPTManifest"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="JobCode"/> 
       <xs:element ref="EstimateHours"/> 
       <xs:element ref="ActualHours"/> 
       <xs:element ref="Density"/> 
       <xs:element ref="NettLitres"/> 
       <xs:element ref="QuitOutLitres"/> 
       <xs:element ref="QuitInLitres"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="QuitOutLitres" type="xs:decimal"/> 
    <xs:element name="QuitInLitres" type="xs:decimal"/> 
    <xs:element name="PTManifestSonicIn"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="ttPTManifest"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
    <xs:element name="JobCode" type="xs:string"/> 
    <xs:element name="NettLitres" type="xs:decimal"/> 
    <xs:element name="EstimateHours" type="xs:decimal"/> 
    <xs:element name="Density" type="xs:decimal"/> 
    <xs:element name="ActualHours" type="xs:decimal"/> 
</xs:schema> 

所需的XML数据输出:

<?xml version="1.0"?> 
<PTManifestSonicIn xsi:noNamespaceSchemaLocation="SampleOut.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <ttPTManifest> 
     <JobCode>000123</JobCode> 
     <EstimateHours>3141.59</EstimateHours> 
     <ActualHours>3141.59</ActualHours> 
     <Density>123.456</Density> 
     <NettLitres>3141.59265358979</NettLitres> 
     <QuitOutLitres>3141.59265358979</QuitOutLitres> 
     <QuitInLitres>3141.59</QuitInLitres> 
    </ttPTManifest> 
</PTManifestSonicIn> 

回答

1

为了转换XML数据,你可以使用下面的样式表:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    version="2.0"> 
    <xsl:output indent="yes"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template 
      match="* 
        [local-name(.)=document(/*/@xsi:noNamespaceSchemaLocation)/*/xs:element[@type=('xs:double', 'xs:float')]/@name] 
        [. castable as xs:double or . castable as xs:float]"> 
     <xsl:copy> 
      <xsl:value-of select="number(.)"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

你可以用下面的样式表转换架构

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

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="@type[.=('xs:double', 'xs:float')]"> 
     <xsl:attribute name="type" select="'xs:decimal'"/> 
    </xsl:template> 

</xsl:stylesheet> 
+0

谢谢你的Mads,我给它一个去并让你知道结果。 –

+0

用于转换数据的样式表效果很好。但是有一个问题,它没有区分数字字符表示的字符元素值和数字元素之间的区别。我应该在我的示例中包含一个字符数据类型元素。 –

+0

我编辑了我原来的帖子,并包含一个新的元素** JobCode **。 –

1

如果您可以使用XSL v2,请使用Mads的答案。 如果你坚持V1,这可如何是好了XSD转换:

<?xml version="1.0" encoding="UTF-8"?> 
<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()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="xs:element[@type='xs:double' or @type='xs:float']"> 
     <xsl:copy> 
      <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute> 
      <xsl:attribute name="type">xs:decimal</xsl:attribute> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

而这可以用来转换XML:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    version="1.0"> 
    <xsl:output indent="yes"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template 
      match="* 
        [local-name(.)=document(/*/@xsi:noNamespaceSchemaLocation)/*/xs:element[@type='xs:double' or @type='xs:float']/@name] 
        [number(.)=number(.)]"> 
     <xsl:copy> 
      <xsl:value-of select="number(.)"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

即使示例显示v1,我仍在使用v2。我在创建帖子时没有看到它。感谢您提供答案。 –

+0

使用XSLT 1.0解决方案更新,该解决方案考虑了引用的XSD文件中的元素类型。 –