Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何在SQL中使用xml命名空间通配符(表中的多个xml文件具有不同的命名空间url)_Sql Server_Xml_Tsql - Fatal编程技术网

Sql server 如何在SQL中使用xml命名空间通配符(表中的多个xml文件具有不同的命名空间url)

Sql server 如何在SQL中使用xml命名空间通配符(表中的多个xml文件具有不同的命名空间url),sql-server,xml,tsql,Sql Server,Xml,Tsql,我有一个SQL文件表,其中存储了多个xml文件以供SQL使用。 xml文件的内容超出了我的控制范围。我只需要将它们用作表的输入。 所有xml文件都具有相同的结构/设置。唯一的问题是,我刚刚意识到其中一些xml文件具有不同的名称空间url(因此在我的表中返回NULL) 我使用xml文件创建一个表,其中xml中的键作为列返回,属性作为行中的值返回。每个xml都作为行返回 所以我现在遇到的问题是,对于名称空间(稍微)不同的所有xml,整行返回NULL 使用的名称空间包括: 和 我使用的查询: WIT

我有一个SQL文件表,其中存储了多个xml文件以供SQL使用。 xml文件的内容超出了我的控制范围。我只需要将它们用作表的输入。 所有xml文件都具有相同的结构/设置。唯一的问题是,我刚刚意识到其中一些xml文件具有不同的名称空间url(因此在我的表中返回NULL)

我使用xml文件创建一个表,其中xml中的键作为列返回,属性作为行中的值返回。每个xml都作为行返回

所以我现在遇到的问题是,对于名称空间(稍微)不同的所有xml,整行返回NULL

使用的名称空间包括: 和

我使用的查询:

WITH XMLNAMESPACES('http://schemas.kvk.nl/xb/query/service/2016/1/0/0' AS ns2) -- Pull namespaces for NS2
SELECT p.*
FROM
(
    SELECT [name]
    ,x.l.value('(ns2:opendataField[@key="SbiBusinessCode"]/@value)[1]','varchar(max)') AS SBI
    ,x.l.value('(ns2:opendataField[@key="FinancialYear"]/@value)[1]','varchar(max)') AS FY
    from dbo.XBRLft t -- filestream table
    CROSS APPLY(SELECT CAST(t.[file_stream] AS XML)) A(xbrl) -- convert filestream into xml.
    CROSS APPLY xbrl.nodes('/opendata') x(l) 
    where x.l.exist('./*/@key')=1 
    ) p  
这将返回仅包含第一个名称空间值的表(因为在查询中使用了该名称空间),但基于具有第二个名称空间的xml的每一行都返回null

所以我尝试使用通配符而不是名称空间,但这只会返回错误

SELECT p.*
FROM
(
    SELECT [name]
    -- Putting all key's as columns and showing the attribute value in row.
    ,x.l.value('(//*:ns2:opendataField[@key="FinancialYear"]/@value)[1]','varchar(max)') AS FY
    from dbo.XBRLft t -- filestream table
    CROSS APPLY(SELECT CAST(t.[file_stream] AS XML)) A(xbrl) -- 
    CROSS APPLY xbrl.nodes('//*:opendata') x(l) -- 
    where x.l.exist('./*/@key')=1 -- 
    ) p
查询中还有更多的键,但在本例中,这些键被忽略了

我可以通过应用2个名称空间url或修复通配符来实现这一点吗

更新

以下是2个示例(每个XML中有1个具有不同名称空间)。我不确定是否可以使用COALESCE,因为这两个XML版本在整个XML中都使用ns2(我需要在查询中添加整个路径以获得不同的键/值,因为XML是分层的)

XML 1:

<opendata xmlns:ns2="http://schemas.kvk.nl/xb/query/service/2016/1/0/0">
  <ns2:opendataField key="DocumentAdoptionDate" value="2017-08-27" />
  <ns2:opendataField key="FinancialYear" value="2016" />
  <ns2:opendataField key="BalanceSheet">
    <ns2:opendataField key="BalanceSheetBeforeAfterAppropriationResultsTitle">
      <ns2:opendataField key="BalanceSheetBeforeAfterAppropriationResults" value="Na" />
    </ns2:opendataField>
    <ns2:opendataField key="BalanceSheetTitle">
      <ns2:opendataField key="Assets" value="548985">
        <ns2:opendataField key="AssetsNoncurrent" value="447571">
          <ns2:opendataField key="PropertyPlantEquipment" value="208215" />
          <ns2:opendataField key="FinancialAssets" value="239355" />
        </ns2:opendataField>
        <ns2:opendataField key="AssetsCurrent" value="101414">
          <ns2:opendataField key="Receivables" value="68895" />
          <ns2:opendataField key="CashAndCashEquivalents" value="32519" />
        </ns2:opendataField>
      </ns2:opendataField>
etc etc
我不确定如何在这里应用您的合并示例,因为这两种XML类型都有ns2,我需要完整的路径


再次感谢

需要名称空间来避免相等名称之间的歧义。从这个角度来看,使用通配符可能非常危险,并可能导致意外的结果

试试这个:

包含一些测试数据的虚拟表

DECLARE @tbl TABLE(id INT IDENTITY, YourXml XML);
INSERT INTO @tbl VALUES
('<root xmlns="blah1">
 <test>Test in 1</test>
 </root>'),
('<root xmlns="blah2">
 <test>Test in 2</test>
 </root>');
--但我们可以使用两个带前缀的名称空间,并使用COALESCE返回返回值的名称空间:

WITH XMLNAMESPACES('blah1' AS ns1
                  ,'blah2' AS ns2)
SELECT t.id
      ,COALESCE(
       t.YourXml.value('(/ns1:root/ns1:test/text())[1]','nvarchar(100)') 
      ,t.YourXml.value('(/ns2:root/ns2:test/text())[1]','nvarchar(100)') 
       ) AS ContentOfTest
FROM @tbl t
--如果可以确定,这是使用通配符的方法,不会导致歧义:

SELECT t.id
      ,t.YourXml.value('(/*:root/*:test/text())[1]','nvarchar(100)') AS ContentOfTest
FROM @tbl t

我真的很感激这一步一步的过程。非常好的回答!非常感谢您的详细解释和反馈。为我的延迟回复道歉,我在度假。我相信联合会是个好主意。但是,我不确定它是否能与我需要使用的XML一起工作。我已经更新了我的初始问题,以包含2个XML版本的示例。@jmhrijdt您不必绑定前缀。事实上,你可以使用任何你喜欢的前缀。只需将
作为ns1
用于其中一个,将
作为ns2
用于另一个,然后在XPath中一致地使用它们。希望这有帮助…@Shnugo,那么你的意思是我需要修改这两个选项的XPath吗?@jmhrijdt完全正确。使用任何前缀声明它们,并在路径中使用此前缀。
WITH XMLNAMESPACES(DEFAULT 'blah1')
SELECT t.id
      ,t.YourXml.value('(/root/test/text())[1]','nvarchar(100)') AS ContentOfTest
FROM @tbl t;
WITH XMLNAMESPACES('blah1' AS ns1
                  ,'blah2' AS ns2)
SELECT t.id
      ,COALESCE(
       t.YourXml.value('(/ns1:root/ns1:test/text())[1]','nvarchar(100)') 
      ,t.YourXml.value('(/ns2:root/ns2:test/text())[1]','nvarchar(100)') 
       ) AS ContentOfTest
FROM @tbl t
SELECT t.id
      ,t.YourXml.value('(/*:root/*:test/text())[1]','nvarchar(100)') AS ContentOfTest
FROM @tbl t