【问题标题】:Parsing xml with more than one xmlns in it in T-SQL在 T-SQL 中解析包含多个 xmlns 的 xml
【发布时间】:2019-01-31 00:44:23
【问题描述】:

我在使用 OPENXML 解析具有两个嵌套 xmlns 命名空间(两者相同)的 XML 文件时遇到问题。

我已经阅读了很多东西,包括this topic on stackexchange,但这对我的情况没有帮助。下面我粘贴了一些 XML 代码(抱歉,所有字段都是波兰语,因为它是来自银行 Web 服务的响应)。如果我选择 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;         

【问题讨论】:

    标签: xml tsql


    【解决方案1】:

    请记住,FROM OPENXML 已过时,不应再使用。还有更强大的native XML-methods

    试试这个

    你的 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);
    

    【讨论】:

      【解决方案2】:

      鉴于您的示例 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 元素的位置,您可以使用local-namename 更改您的XPath:

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

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

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多