XML 数据类型转换

标签 xml xslt xsd xslt-2.0

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

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

XSLT 中是否有一种方法可以识别 Float/Double 数据类型的元素并将其转换为十进制。我认为这可能是主 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>

所需架构输出:

<?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>

最佳答案

为了转换 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>

关于XML 数据类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12486139/

相关文章:

java - Jersey WADL : How do you rename generated XSDs

xml - 从 XSD 模式生成用于测试的 XML 文件

android - 如何从 xml 元素中获取成员值

c# - 在 xsl 转换后将 <?xml version ="1.0"?> 添加到 xml 文件的顶部

c# - 将 Linq 转换为 XSLT

java - JBOSS AS 7 中的 XSL FO 无法进行 XSLT 转换

Android - 如何通过 XML 编辑图像的大小以用作图标

xml - 如何从 XSLT 中获取未解析的实体属性值?

xml - XSL递归轴故障?

java - 如何注释 JAXB 属性以使用 xsd :time rather than xsd:datetime?