将具有相同标记的XML值分隔到不同的行SQL Server中

时间:2015-10-20 18:31:19

标签: sql sql-server xml xquery xquery-sql

我有一个XML文件,我试图解析。 XML是使用

通过Excel创建的
  

另存为XML

由于XML文件是从Microsoft Excel创建的,因此它具有以下标题:

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:html="http://www.w3.org/TR/REC-html40">

我想要提取的数据是按以下方式设置的:

<Row ss:AutoFitHeight="0" ss:Height="30">
    <Cell ss:StyleID="s22"/>
    <Cell ss:StyleID="s24"><Data ss:Type="String">Jane Doe</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">JaneDoe</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">XYZ</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">(555) 555-5555</Data></Cell>
    <Cell ss:StyleID="s22"/>
   </Row>

现在,我的查询如下:

;WITH XMLNAMESPACES ('urn:schemas-microsoft-com:office:spreadsheet' as ss)

select * from (
select X.value('local-name(.)[1]','varchar(max)') as Name,
X.value('.[1]','varchar(max)') as Value
from @allUsers.nodes('//*') as T(X)
    ) a
where Name  = 'Data'

给我这些结果:

Name    Value
----    -----------
Data    Jane Doe
Data    JaneDoe
Data    XYZ
Data    (555)555-5555

我想要做的是将它分成4行,所以我有类似的东西:

Name      UserName    Address    Phone
-----     ----------  ---------  ----------
Jane Doe  JaneDoe     XYZ        (555)-555-5555

我尝试选择列

X.value('.[2]','varchar(max)') as UserName

但我只获取了所有NULL值。

有没有办法做到这一点?

XML文件的一般结构如下:

<Workbook>
  <DocumentProperties>
  </DocumentProperties>
  <ExcelWorkbook>
  </ExcelWorkbook>
  <Styles>
    <Style>
    </Style>
  </Styles>
  <Worksheet>
    <Table>
      <Column.../>
      <Column.../>
      <Column.../>
      <Row>
        <Cell.../>
        <Cell><Data>...</Data></Cell>
        <Cell><Data>...</Data></Cell>
        <Cell><Data>...</Data></Cell>
        <Cell><Data>...</Data></Cell>
        <Cell.../>
      </Row>
      ...
    </Table>
  </Worksheet>

我想要获取的信息位于<Data>...</Data>字段

修改

从我对这个问题的表达方式来看,似乎已经编写了标题名称,但它们实际上被读作<Cell><Data><Data/></Cell>中的行。我也不确定该部分的用途是什么

这是<Row>部分的开头:

<Table ss:ExpandedColumnCount="6" ss:ExpandedRowCount="2685" x:FullColumns="1"
   x:FullRows="1">
   <Column ss:AutoFitWidth="0" ss:Width="26.25"/>
   <Column ss:AutoFitWidth="0" ss:Width="117" ss:Span="3"/>
   <Column ss:Index="6" ss:AutoFitWidth="0" ss:Width="29.25"/>
   <Row ss:AutoFitHeight="0" ss:Height="60"> --Contains the header names
    <Cell ss:StyleID="s22"/>
    <Cell ss:StyleID="s23"><Data ss:Type="String">Name</Data></Cell>
    <Cell ss:StyleID="s23"><Data ss:Type="String">UserName</Data></Cell>
    <Cell ss:StyleID="s23"><Data ss:Type="String">Address</Data></Cell>
    <Cell ss:StyleID="s23"><Data ss:Type="String">Telephone Number</Data></Cell>
    <Cell ss:StyleID="s22"/>
   </Row>

   <Row ss:AutoFitHeight="0" ss:Height="30"> --First record I would like to extract
    <Cell ss:StyleID="s22"/>
    <Cell ss:StyleID="s24"><Data ss:Type="String">John Smith</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">JSmith</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">ABC</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">(999) 999-9999</Data></Cell>
    <Cell ss:StyleID="s22"/>
   </Row>

2 个答案:

答案 0 :(得分:2)

同一个用户有两个非常相似的问题。 OP决定删除一个并将其结合在一起,并要求我将我的答案复制到此主题。

请注意必须声明为“DEFAULT”的xmlns命名空间:

简化了你的XML,但这个想法应该没问题......

{{1}}

答案 1 :(得分:1)

尝试这样:我添加了一个根元素来暗示命名空间,你必须把它拿出来(也来自XPath),但你可以通过简单的复制,粘贴在空的查询窗口中测试它并执行:

DECLARE @allUsers XML=
'<root xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
   <Row ss:AutoFitHeight="0" ss:Height="30">
    <Cell ss:StyleID="s22"/>
    <Cell ss:StyleID="s24"><Data ss:Type="String">Jane Doe</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">JaneDoe</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">XYZ</Data></Cell>
    <Cell ss:StyleID="s24"><Data ss:Type="String">(555) 555-5555</Data></Cell>
    <Cell ss:StyleID="s22"/>
   </Row>
</root>';

;WITH XMLNAMESPACES ('urn:schemas-microsoft-com:office:spreadsheet' as ss)
SELECT T.X.value('Cell[1]/Data[1]','varchar(max)') AS DontKnow1
      ,T.X.value('Cell[2]/Data[1]','varchar(max)') AS Name
      ,T.X.value('Cell[3]/Data[1]','varchar(max)') AS UserName
      ,T.X.value('Cell[4]/Data[1]','varchar(max)') AS DontKnow2
      ,T.X.value('Cell[5]/Data[1]','varchar(max)') AS Telephone
      ,T.X.value('Cell[6]/Data[1]','varchar(max)') AS DontKnow3
FROM @allUsers.nodes('/root/Row') as T(X)

编辑:您的路径将类似于/Workbook[1]/Worksheet[1]/Table[1]/Row[1]

祝你好运!