如何使用xslt转换此xml

时间:2017-07-06 03:56:58

标签: xml xslt ssis

我有以下格式的XML:

<?xml version="1.0" encoding="utf-8"?>
<dataset  xmlns="http://developer.cognos.com/schemas/xmldata/1/"  xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
    <metadata>
          <item name="Col1" type="xs:string" length="14"/>
          <item name="Col2" type="xs:string" length="92"/>
          <item name="Col3" type="xs:string" length="66"/>
          <item name="Col4 With Space" type="xs:string" length="32"/>
    </metadata>
    <data>
        <row>
            <value>SomeVal1</value>
            <value>SomeVal2</value>
            <value>SomeVal3</value>
            <value>SomeVal4</value>
        </row>
        <row>
            <value>SomeVal11</value>
            <value>SomeVal22</value>
            <value>SomeVal33</value>
            <value>SomeVal44</value>
        </row>
    </data>
</dataset>

我想将其转换为这种格式:

<?xml version="1.0" encoding="utf-8"?>
<dataset>
    <data>
        <row>
            <Col1 type="xs:string" length="14">SomeVal1</Col1>
            <Col2 type="xs:string" length="92">SomeVal2</Col2>
            <Col3 type="xs:string" length="66">SomeVal3</Col3>
            <Col4_With_Space type="xs:string" length="32">SomeVal4</Col4_With_Space>
        </row>
        <row>
            <Col1 type="xs:string" length="14">SomeVal11</Col1>
            <Col2 type="xs:string" length="92">SomeVal22</Col2>
            <Col3 type="xs:string" length="66">SomeVal33</Col3>
            <Col4_With_Space type="xs:string" length="32">SomeVal44</Col4_With_Space>
        </row>
    </data>
</dataset>

我之前从未使用过xslt,而且我已经超出了我的深度。我试过这样的事情(这不起作用)但是我被卡住了。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0">
<xsl:output encoding="UTF-8" indent="yes" method="xml" standalone="no" omit-xml-declaration="no"/>
    <xsl:template match="dataset">
        <xsl:for-each select="data/row">
            <Col1 select="1"/>
            <Col2 select="2"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

想要转型的原因是SSIS&#34;数据流&#34; &#34; XML Source&#34;不识别第一种格式。我试图将数据从XML导入到数据库表中。 &#34; XML Source&#34;使用第二种格式但不是第一种格式。

我想我应该补充一点,不能保证XML元数据始终是相同的,因此转换需要从元数据中获取列名和类型,而不是硬编码。

1 个答案:

答案 0 :(得分:2)

  

我之前从未使用过xslt,而且我不在我的身边。

这当然不适合初学者。

正如我在您的问题的评论中提到的,您的第一个问题是您的源XML将其所有元素放在命名空间中。您需要在样式表中声明相同的名称空间,为其分配前缀并使用该前缀来处理源XML中的元素。

您尝试的另一个问题是您实际上并未从源XML获取任何数据。

<Col1 select="1"/>

将为XML中的每一行输出相同的静态元素。

现在,真正的复杂功能是从metadata部分获取列名称和属性,并将它们与当前行中的相应单元格值进行配对。这可以通过以下方式完成:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cog="http://developer.cognos.com/schemas/xmldata/1/" 
exclude-result-prefixes="cog">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/cog:dataset">
    <xsl:variable name="cols" select="cog:metadata/cog:item" />
    <dataset>
        <data>
            <xsl:for-each select="cog:data/cog:row">
                <xsl:variable name="curr-row-cells" select="cog:value" />
                <row>
                    <xsl:for-each select="$cols">
                        <xsl:variable name="i" select="position()" />
                        <xsl:element name="{translate(@name, ' ', '_')}">
                            <xsl:copy-of select="@type | @length"/>
                            <xsl:value-of select="$curr-row-cells[$i]" />
                        </xsl:element>
                    </xsl:for-each>
                </row>
            </xsl:for-each>
        </data>
    </dataset>
</xsl:template>

</xsl:stylesheet>

<强>结果

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <data>
    <row>
      <Col1 type="xs:string" length="14">SomeVal1</Col1>
      <Col2 type="xs:string" length="92">SomeVal2</Col2>
      <Col3 type="xs:string" length="66">SomeVal3</Col3>
      <Col4_With_Space type="xs:string" length="32">SomeVal4</Col4_With_Space>
    </row>
    <row>
      <Col1 type="xs:string" length="14">SomeVal11</Col1>
      <Col2 type="xs:string" length="92">SomeVal22</Col2>
      <Col3 type="xs:string" length="66">SomeVal33</Col3>
      <Col4_With_Space type="xs:string" length="32">SomeVal44</Col4_With_Space>
    </row>
  </data>
</dataset>

重要:

提供的列名称不一定是有效的XML元素名称。在这个例子中,"Col4 With Space"包含我已经转换为下划线的空格 - 但是还有许多其他潜在的陷阱可能导致名称无法使用并产生致命错误。