在SSIS中将复杂XML转换为可用格式

时间:2014-05-20 12:20:49

标签: sql-server xml xslt ssis

我一直在学习SQL Server(痛苦而且缓慢),最后得到了我想要做的大事,但是有一个XML导入过程让我感到沮丧。我有一个复杂的XML文件,如下所示(有关此XML的更多详细信息,请访问:http://wiki.eve-id.net/APIv2_Corp_AssetList_XML):

<?xml version='1.0' encoding='UTF-8'?>
<eveapi version="2">
  <currentTime>2010-12-19 07:15:16</currentTime>
  <result>
    <rowset name="assets" key="itemID" columns="itemID,locationID,typeID,quantity,flag,singleton">
      <row itemID="961254083" locationID="30001161" typeID="17177" quantity="1" flag="0" singleton="1" />
      <row itemID="961256074" locationID="30001161" typeID="27672" quantity="1" flag="0" singleton="1" />
      <row itemID="1270658107" locationID="30002583" typeID="17176" quantity="1" flag="0" singleton="1" />
      <row itemID="1000474513775" locationID="30002583" typeID="17407" quantity="1" flag="0" singleton="1">
        <rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
          <row itemID="1000515794105" typeID="255" quantity="1" flag="27" singleton="1" />
        </rowset>
      </row>
      <row itemID="1000474513607" locationID="30002583" typeID="17406" quantity="1" flag="0" singleton="1">
        <rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
          <row itemID="1000515772705" typeID="17686" quantity="1" flag="27" singleton="1" />
        </rowset>
      </row>
    </rowset>
  </result>
  <cachedUntil>2010-12-19 23:40:24</cachedUntil>
</eveapi>

所以,当我尝试使用XML Source工具导入它时,SSIS自然会嗤之以鼻,因为它是“复杂的”XML(咕噜咕噜)。理想情况下,我希望能够将此内容放入SSIS数据流中,以便将其转储到SQL数据库中的表中。时髦的东西带有额外的嵌套行,这些是嵌套在其他项目中的项目,我想保留嵌套信息。理想情况下,我想要做的是创建一个包含父项的itemID的新列,如果它位于顶层,则为0或null。这还需要复制父项的locationID。

Ergo,最终输出将是一个包含以下行的表:itemID,locationID,typeID,quantity,flag,singleton,parentID。鉴于上面的示例输入,输出应该看起来像这样(假设.csv格式):

itemID, locationID, typeID, quantity, flag, singleton, parentID
961254083, 30001161, 17177, 1, 0, 1, 0
961256074, 30001161, 27672, 1, 0, 1, 0
1270658107, 30002583, 17176, 1, 0, 1, 0
1000474513775, 30002583, 17407, 1, 0, 1, 0
1000515794105, 30002583, 255, 1, 27, 1, 1000474513775
1000474513607, 30002583, 17406, 1, 0, 1, 0
1000515772705, 30002583, 17686, 1, 27, 1, 1000474513607

从我一直在谷歌搜索(这是谷歌的精彩力量)这可能是一个XSLT,但我对这些事情的知识目前是微不足道的,刚刚学会了如何使用SSIS和玩XML大约两周前以这种方式提交文件。我希望能够在构建可以进行此转换的XSLT文件或其他可能更好的方式上获得一些帮助。

另外一个注意事项:无论解决方案是什么,它都不能涉及任何类型的手动输入。我这样做是为了从手动输入系统迁移出来,所以任何手动输入都会完全违背这样做的目的。

非常感谢!

1 个答案:

答案 0 :(得分:0)

您的CSV样式输出实际上非常简单直接通过XSLT获得。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="utf-8" />

  <xsl:template match="/">
    <xsl:text>itemID, locationID, typeID, quantity, flag, singleton, parentID&#xA;</xsl:text>
    <xsl:apply-templates select="//row" />
  </xsl:template>

  <xsl:template match="row">
    <xsl:variable name="p" select="ancestor::row[1]" />
    <xsl:value-of select="concat(@itemID, ', ')" />
    <xsl:value-of select="concat(@locationID|$p/@locationID, ', ')" />
    <xsl:value-of select="concat(@typeID, ', ')" />
    <xsl:value-of select="concat(@quantity, ', ')" />
    <xsl:value-of select="concat(@flag, ', ')" />
    <xsl:value-of select="concat(@singleton, ', ')" />
    <xsl:value-of select="concat($p/@itemID, '&#xA;')" />
  </xsl:template>   
</xsl:stylesheet>

生成

itemID, locationID, typeID, quantity, flag, singleton, parentID
961254083, 30001161, 17177, 1, 0, 1, 
961256074, 30001161, 27672, 1, 0, 1, 
1270658107, 30002583, 17176, 1, 0, 1, 
1000474513775, 30002583, 17407, 1, 0, 1, 
1000515794105, 30002583, 255, 1, 27, 1, 1000474513775
1000474513607, 30002583, 17406, 1, 0, 1, 
1000515772705, 30002583, 17686, 1, 27, 1, 1000474513607

XSLT程序中唯一没有价值的就是这一行

<xsl:value-of select="concat(@locationID|$p/@locationID, ', ')" />

此处@locationID|$p/@locationID选择当前<row> @locationID union 和容器<row> union 。这个XPath最多可以返回两个属性节点,但这里的基本假设是它们是互斥的。

这是一个小技巧,使线条在两种情况下都可以工作,同时避免条件限制。但是,如果我的基本假设是错误的,那么表达式的结果也是错误的。

如果您在理解解决方案时遇到困难,请阅读<xsl:apply-templates>的工作原理。