TSQL + XML节点查询& XMLNameSpaces - 获取值列表

时间:2014-01-13 23:23:16

标签: sql sql-server xml tsql xml-namespaces

我一直在看这里的示例,但我仍然在努力正确地查询我的XML。 我一直试图通过SQL xml.nodes查询来分解我的XML,但我没有得到任何结果

这是XML示例:

<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope 
    xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" 
    xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates
    </gesmes:subject>
    <gesmes:Sender>
        <gesmes:name>European Central Bank
        </gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time="2013-12-09">
            <Cube currency="USD" rate="1.3722"/>    
            <Cube currency="EUR" rate="1.0"/>
            </Cube>
        <Cube time="2013-12-10">
            <Cube currency="USD" rate="1.5555"/>
            <Cube currency="EUR" rate="1.2"/>
        </Cube>
    </Cube>
</gesmes:Envelope>

我需要按以下格式将这些值插入表中:

MyDate      Currency    Rate
2013-12-09  USD         1.3722
2013-12-09  EUR         1.0
2013-12-10  USD         1.5555
2013-12-10  EUR         1.2

经过多次尝试后,我想我会尝试删除gesmes *节点并将其替换为实际设法获取值。

这是我使用的SQL:

    declare @xml as xml;
    set @xml = 
    '<Root>
    <Cube>
        <Cube time="2013-12-09">
            <Cube currency="USD" rate="1.3722"/>
            <Cube currency="EUR" rate="1.0"/>
            </Cube>
        <Cube time="2013-12-10">
            <Cube currency="USD" rate="1.5555"/>
            <Cube currency="EUR" rate="1.2"/>
        </Cube>
    </Cube>
    </Root>'

    SELECT FXDate.value('@time', 'varchar(100)') AS FXDATE
        ,FXRates.value('@currency','varchar(100)') AS FXCurrency
        ,FXRates.value('@rate','varchar(100)') AS FXRate
    FROM @XML.nodes('Root/Cube/Cube') as Test(FXDate) 
    CROSS APPLY Test.FXDate.nodes('Cube') as Test2(FXRates);

然后我意识到它可能与命名空间(?)有关,因为我注意到其他人指出这是为了别人的查询。所以现在我更倾向于如何让SQL使用命名空间。由于此文件将作为参数发送,我必须使用名称空间。

这是我尝试使用命名空间的SQL,但结果中没有任何内容。任何反馈/答案将非常感谢。谢谢!

declare @xml as xml;
set @xml = 
'<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope 
    xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" 
    xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
    <gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
    <Cube time="2013-12-09">
        <Cube currency="USD" rate="1.3722"/>
        <Cube currency="EUR" rate="1.0"/>
        </Cube>
    <Cube time="2013-12-10">
        <Cube currency="USD" rate="1.5555"/>
        <Cube currency="EUR" rate="1.2"/>
    </Cube>
</Cube>
</gesmes:Envelope>'

select @xml

;with xmlnamespaces('http://www.ecb.int/vocabulary/2002-08-01/eurofxref' AS ns
,'http://www.gesmes.org/xml/2002-08-01' as ns2 )
SELECT FXDate.value('@time', 'varchar(100)')
FROM @XML.nodes('ns:gesmes/Cube/Cube/Cube') as Test(FXDate)

1 个答案:

答案 0 :(得分:2)

试试这个:

;WITH XMLNAMESPACES (DEFAULT 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref',
    'http://www.gesmes.org/xml/2002-08-01' AS ns)
SELECT 
    FXDate = FXDate.value('../@time', 'varchar(100)'),
    FXCurrency = FXDate.value('@currency','varchar(100)'),
    FXRate = FXDate.value('@rate','varchar(100)') 
FROM 
    @XML.nodes('ns:Envelope/Cube/Cube/Cube') as Test(FXDate) 

基本上,XML中的默认 XML命名空间也应该用作查询中的默认XML命名空间,而第二个XML命名空间只是列出了您选择的前缀。

此外,您的XPath在顶部使用/Root时出错 - 此处的根元素在您的XML中称为<Envelope>

我也删除了CROSS APPLY,因为它似乎没有必要 - 只需选择最低级<Cube>条目,然后使用../@time引用“一级”属性“父”<Cube> XML元素。