2012-09-18 154 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文件中的元素類型。 –