在T-SQL中解析具有多个xmlns的xml

3
我在使用OPENXML解析一个包含两个嵌套xmlns命名空间(均相同)的XML文件时遇到了问题。
我已经阅读了很多相关资料,包括这个stackexchange主题,但它并不能解决我的问题。以下是一些XML代码(抱歉所有字段都是波兰语,因为它是银行webservice的响应)。如果我选择DaneZapytaniaFin对象,则...
;WITH XMLNAMESPACES(DEFAULT 'http://bik.pl/cc/big')
SELECT * FROM OPENXML(@idoc, '/BIGIMResponse/DaneZapytaniaFin')

我得到了所有的值。

但是当我尝试获取例如名称字段时

;WITH XMLNAMESPACES(DEFAULT 'http://bik.pl/cc/big')
SELECT * FROM OPENXML(@idoc, '/BIGIMResponse/DaneZapytaniaFin/dane-id-kons/imie') 

我只得到了空值。

当我试图获取它的父节点,dane-id-kons时,结果也是一样的。

;WITH XMLNAMESPACES(DEFAULT 'http://bik.pl/cc/big')
SELECT * FROM OPENXML(@idoc, '/BIGIMResponse/DaneZapytaniaFin/dane-id-kons')

这是空值。

有人能给我一些关于如何获取这些值的建议吗?提前感谢!

我的XML文件如下:

<?xml version="1.0" encoding="utf-8"?>
<BIGIMResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <DaneZapytaniaFin>
        <forma-pr-podm forma-pr-podm="01" xmlns="http://bik.pl/cc/big" />
        <dane-id-kons form-przek-nazw-i-im="01" imie="NAME" nazw="SURNAME" pesel="1234567890" rodz-dok-tozs="ID" seria-nr-dok-tozs="ABC123456" obywatelstwo="PL" xmlns="http://bik.pl/cc/big" />
        <daty-upow data-up-15-1="2019-11-22T00:00:00" data-up-24-1="2019-11-22T00:00:00" data-up-bik="2019-11-22T00:00:00" data-up-zbp="2019-11-22T00:00:00" xmlns="http://bik.pl/cc/big" />
    </DaneZapytaniaFin>
</BIGIMResponse>

我正在直接从文件路径读取它,例如:

create table #p_TempDM (dane xml)
declare @idoc INT
declare @sql varchar(max) 
    set @sql = '
        insert into #p_TempDM select CONVERT(xml, bulkcolumn, 2) imp from
        openrowset (bulk '''+@filePath+''', single_blob) as dane
        '
        exec (@sql)

declare @x xml

select @x =      dane from  #p_TempDM   
                 EXEC sp_xml_preparedocument
                 @idoc OUTPUT,
                 @x;         
2个回答

2
请注意,FROM OPENXML已经过时,不应再使用。现在有更强大的本机XML方法可供使用。
请尝试以下操作:
您的XML
DECLARE @xml XML=
'<?xml version="1.0" encoding="utf-8"?>
<BIGIMResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <DaneZapytaniaFin>
        <forma-pr-podm forma-pr-podm="01" xmlns="http://bik.pl/cc/big" />
        <dane-id-kons form-przek-nazw-i-im="01" imie="NAME" nazw="SURNAME" pesel="1234567890" rodz-dok-tozs="ID" seria-nr-dok-tozs="ABC123456" obywatelstwo="PL" xmlns="http://bik.pl/cc/big" />
        <daty-upow data-up-15-1="2019-11-22T00:00:00" data-up-24-1="2019-11-22T00:00:00" data-up-bik="2019-11-22T00:00:00" data-up-zbp="2019-11-22T00:00:00" xmlns="http://bik.pl/cc/big" />
    </DaneZapytaniaFin>
</BIGIMResponse>';

--在这种情况下,我声明了默认命名空间,但是需要注意的是!-前两个级别不属于此默认命名空间(它在更深的级别上声明)。为了解决这个问题,我使用了命名空间通配符(就像这里的/*:BIGIMResponse)。一般来说,这并不推荐,但在这里似乎是可以接受的。您可以使用此方法单独和类型化地处理每个值:

最初的回答已经解释了如何声明默认命名空间以及如何使用命名空间通配符来解决此问题。

WITH XMLNAMESPACES(DEFAULT 'http://bik.pl/cc/big')
SELECT @xml.value('(/*:BIGIMResponse/*:DaneZapytaniaFin/forma-pr-podm/@forma-pr-podm)[1]','int')
      ,@xml.value('(/*:BIGIMResponse/*:DaneZapytaniaFin/dane-id-kons/@form-przek-nazw-i-im)[1]','int') 
      ,@xml.value('(/*:BIGIMResponse/*:DaneZapytaniaFin/dane-id-kons/@imie)[1]','nvarchar(max)') 
      --and so on

--另一种方法是更通用的将读取到EAV

SELECT A.nds.value('local-name(.)','nvarchar(max)') AS ElementName
      ,B.attrs.value('local-name(.)','nvarchar(max)') AS AttributeName
      ,B.attrs.value('.','nvarchar(max)') AS AttributeValue
FROM @xml.nodes('//BIGIMResponse/DaneZapytaniaFin/*') A(nds)
CROSS APPLY A.nds.nodes('@*') B(attrs);

0

根据您的示例XML,如果您正在尝试选择名称字段,则XPath是错误的:

/BIGIMResponse/DaneZapytaniaFin/dane-id-kons/imie

这选择了一个元素,但您正在尝试选择一个属性

尝试使用以下内容选择该属性:

/BIGIMResponse/DaneZapytaniaFin/dane-id-kons/@imie

请注意,@指定您正在尝试选择属性。但是,如果您在XPath中遇到默认命名空间问题,可以尝试以下方法(它在XPath评估器中对我有效):

/BIGIMResponse/DaneZapytaniaFin/*[name()='dane-id-kons']/@imie

对于您要选择dane-id-kons元素的位置,您可以更改XPath以使用local-namename进行查找:

/BIGIMResponse/DaneZapytaniaFin/*[local-name()="dane-id-kons"]

/BIGIMResponse/DaneZapytaniaFin/*[name()="dane-id-kons"]

希望这可以帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接