无法从命名空间中读取xml节点

时间:2018-06-18 12:33:48

标签: sql sql-server xml tsql namespaces

基本上我有一个类似于这个的XML文件:

Update t set te_system_ref = ('-' + Convert(nvarchar(50),te_system_ref))
from (
select row_number() over (partition by te_system_ref order by (select 0)) as rn, te_system_ref, te_event from ticket_events where te_system_ref in 
(
select te_system_ref from ticket_events where te_event = 'VQ5 hard copy follows' and te_date between '04/12/17' and '18/06/18 23:59:59' group by te_system_ref having count (te_event) > 10
)
and te_event =  'VQ5 hard copy follows'
)t
where t.rn <> 1 and te_system_ref not like '-%'

我这样插入:

<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <Cube>
        <Cube time="2018-06-15">
            <Cube currency="USD" rate="1.2345"/>
            <Cube currency="ZAR" rate="10.1"/>
        </Cube>
        <Cube time="2018-06-16">
            <Cube currency="USD" rate="1.1596"/>
            <Cube currency="ZAR" rate="9.546"/>
        </Cube>
    </Cube>
</gesmes:Envelope>
然后我尝试读取时间,货币和费率:

INSERT INTO 
    fxRatesXml(xmlData, updatedOn)
SELECT 
    CONVERT(XML, bulkColumn), 
    GETDATE() 
FROM 
    OPENROWSET(BULK 'I:\Downloads\eurofxref-hist-90d.xml', SINGLE_BLOB) as fxRateXmlData;

但没有运气。

我不确定在哪里出错,任何帮助都会受到赞赏。

已更新

更新的XML更具体。它可以包括超过2个立方体的时间,每个立方体时间超过2个货币。

我如何迭代/选择它们?

1 个答案:

答案 0 :(得分:1)

填充@xml变量后,请尝试使用EXEC sp_xml_preparedocument定义所需的命名空间,而不是使用;WITH XMLNAMESPACES

我在xml的末尾添加了缺少的结束标记</gesmes:Envelope>,因此我使用以下xml测试了我的查询:

<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <Cube>
        <Cube time="2018-06-15">
            <Cube currency="USD" rate="1.1596"/>
        </Cube>
    </Cube>
</gesmes:Envelope>

这是从xml变量@ xml中检索数据的查询:

declare @xml xml = '<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> <Cube> <Cube time="2018-06-15"> <Cube currency="USD" rate="1.1596"/> </Cube> </Cube> </gesmes:Envelope>'

;WITH XMLNAMESPACES('http://www.gesmes.org/xml/2002-08-01' AS gesmes,
                    'http://www.ecb.int/vocabulary/2002-08-01/eurofxref' as ns)
SELECT 
    T.X.value('ns:Cube[1]/@currency','varchar(500)') AS [currency],
    T.X.value('ns:Cube[1]/@rate','varchar(500)') AS [rate],
    T.X.value('./@time','varchar(500)') AS [time]
FROM 
    @xml.nodes('/gesmes:Envelope/ns:Cube/ns:Cube') AS T(X)

结果:

enter image description here

要处理多个<Cube>代码:

<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <Cube>
        <Cube time="2018-06-15">
            <Cube currency="USD" rate="1.2345"/>
            <Cube currency="ZAR" rate="10.1"/>
        </Cube>
        <Cube time="2018-06-16">
            <Cube currency="USD" rate="1.1596"/>
            <Cube currency="ZAR" rate="9.546"/>
        </Cube>
    </Cube>
</gesmes:Envelope>

您可以使用此查询:

declare @xml xml ='<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> <Cube> <Cube time="2018-06-15"> <Cube currency="USD" rate="1.2345"/> <Cube currency="ZAR" rate="10.1"/> </Cube> <Cube time="2018-06-16"> <Cube currency="USD" rate="1.1596"/> <Cube currency="ZAR" rate="9.546"/> </Cube> </Cube> </gesmes:Envelope>'    

;WITH XMLNAMESPACES('http://www.gesmes.org/xml/2002-08-01' AS gesmes,
    'http://www.ecb.int/vocabulary/2002-08-01/eurofxref' as ns)
SELECT T.X.value('(.)[1]/@currency','varchar(500)') AS [currency]
     ,T.X.value('(.)[1]/@rate','varchar(500)') AS [rate]
     ,T.X.value('(..)[1]/@time','varchar(500)') AS [time]
FROM @xml.nodes('/gesmes:Envelope/ns:Cube/ns:Cube/ns:Cube') AS T(X)

结果:

enter image description here