使用 OPENXML 从 XML 文件读取时获取 NULL 值

Getting NULL values while using OPENXML to read from XML file

为什么我在尝试将 XML 文档(下面的文件示例)读入 SQL 服务器时得到 NULL 值?我认为这是由于阅读文件。 SQL 的第一部分似乎没问题 - 我在 SQLSERVER 网格中看到 xml 文件。但不知道如何读取数据。想法是 - 我想将 XML 文件导入 SQL 服务器,使用简单的 SQL 查询进行一些数据清理,然后将其导入其他系统。

这个 XML 使用 DTD。

感谢您的帮助。

SELECT CONVERT(XML, BulkColumn,2) AS BulkColumn
FROM OPENROWSET(BULK 'H:\file.xml', SINGLE_BLOB) AS x;

DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)    

SELECT @XML = XMLData FROM XMLwithOpenXML WHERE ID = '1' -- The row to process    

EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML


SELECT *
FROM OPENXML(@hDoc, '/BMECAT/HEADER/CATALOG/',1)
WITH 
(
language nvarchar(max)
)


EXEC sp_xml_removedocument @hDoc
GO


<!-- Generated by crossbase mediasolution GmbH (http://www.crossbase.de) -->
<BMECAT xmlns="http://www.bmecat.org/bmecat/1.2/bmecat_new_catalog" version="1.2">
<HEADER>
<CATALOG>
  <LANGUAGE>DE</LANGUAGE>
  <CATALOG_ID>ML103</CATALOG_ID>
  <CATALOG_VERSION>1</CATALOG_VERSION>
  <DATETIME type="generation_date">
    <DATE>2015-10-12</DATE>
    <TIME>07:10:42</TIME>
    <TIMEZONE>+02:00</TIMEZONE>
  </DATETIME>
</CATALOG>
<BUYER>
  <ADDRESS type="buyer" />
</BUYER>
<SUPPLIER>
  <SUPPLIER_NAME>GmbH</SUPPLIER_NAME>
  <ADDRESS type="supplier">
    <NAME>GmbH</NAME>
    <NAME2>fabrik</NAME2>
    <STREET>e 1</STREET>
    <ZIP>6973</ZIP>
    <CITY>st</CITY>
    <COUNTRY>eich</COUNTRY>
    <PHONE>05-0</PHONE>
    <FAX>705-44</FAX>
    <EMAIL>info@com</EMAIL>
    <URL>www.com</URL>
  </ADDRESS>
</SUPPLIER>

感谢原始文件。我把它下载下来,可以毫无问题地阅读它:。像这样尝试:

DECLARE @yourXML AS XML=
(
SELECT CONVERT(XML, BulkColumn,2) AS BulkColumn
FROM OPENROWSET(BULK 'H:\file.xml', SINGLE_BLOB) AS x
);

--simple approach
WITH XMLNAMESPACES(DEFAULT 'http://www.bmecat.org/bmecat/1.2/bmecat_new_catalog')
SELECT @YourXML.value('(/BMECAT/HEADER/CATALOG/LANGUAGE)[1]','varchar(2)');

--with OPENXML
DECLARE @hDoc INT;
EXEC sp_xml_preparedocument @hDoc output, @YourXML,'<root xmlns:dflt="http://www.bmecat.org/bmecat/1.2/bmecat_new_catalog" />';

SELECT LANGUAGE
FROM OPENXML(@hDoc,'/dflt:BMECAT/dflt:HEADER/dflt:CATALOG') 
WITH(LANGUAGE VARCHAR(MAX) 'dflt:LANGUAGE'); 

EXEC sp_xml_removedocument @hDoc
GO

接下来您会找到一堆 XML 示例(有或没有命名空间)来比较并找到您需要的最佳方法。只需将其粘贴到空查询 window 中并执行:

DECLARE @xmlNaked XML='<root><element test="SomeValue"/></root>';
DECLARE @xmlNamespace XML='<root xmlns="http://testNS" xmlns:ns2="http://testNS/ns2"><element test="SomeValue"/><ns2:namespaced test2="another value"/></root>';

--Normale approach
SELECT @xmlNaked.value('(/root/element/@test)[1]','varchar(max)') AS TheElement;

--No return value due to namespace
SELECT @xmlNamespace.value('(/root/element/@test)[1]','varchar(max)') AS TheElementMissing
      ,@xmlNamespace.value('(/root/namespaced/@test2)[1]','varchar(max)') AS NamespacedMissing; 

--Declaring default namespace before (xmlns is the default, ns2 additional)
WITH XMLNAMESPACES(DEFAULT 'http://testNS')
SELECT @xmlNamespace.value('(/root/element/@test)[1]','varchar(max)') AS TheElement
      ,@xmlNamespace.value('(/root/namespaced/@test2)[1]','varchar(max)') AS NamespacedMissing; 

--Declaring default namespace and additional namespace
WITH XMLNAMESPACES('http://testNS/ns2' AS ns2, DEFAULT 'http://testNS')
SELECT @xmlNamespace.value('(/root/element/@test)[1]','varchar(max)') AS TheElement
      ,@xmlNamespace.value('(/root/ns2:namespaced/@test2)[1]','varchar(max)') AS NamespacedMissing; 

--now with OPENXML, namespaces must be introduced in sp_xml_preparedocument
DECLARE @i INT, @ns VARCHAR(100);
EXEC sp_xml_preparedocument @i output, @xmlNaked;
SELECT test AS TheElement FROM OPENXML(@i,'/root/element',2) WITH(test VARCHAR(MAX) '@test') 

--not return value due to namespace
EXEC sp_xml_preparedocument @i output, @xmlNamespace;
SELECT test AS TheElementMissing FROM OPENXML(@i,'/root/element',2) WITH(test VARCHAR(MAX) '@test') 

--There's AFAIK no "direct" declaration of the default namespace possible. Look at the declaration of "dflt" namespace
EXEC sp_xml_preparedocument @i output, @xmlNamespace,'<root xmlns:dflt="http://testNS" />';
SELECT test AS TheElement FROM OPENXML(@i,'/dflt:root/dflt:element') WITH(test VARCHAR(MAX)) 

--Now the full thing
EXEC sp_xml_preparedocument @i output, @xmlNamespace,'<root xmlns:dflt="http://testNS" xmlns:ns2="http://testNS/ns2"/>';
SELECT test AS TheElement,test2 AS Namespace 
FROM OPENXML(@i,'/dflt:root',2) 
     WITH   (test VARCHAR(MAX) 'dflt:element/@test'
            ,test2 VARCHAR(MAX) 'ns2:namespaced/@test2'  )

是的,您的示例有效。两种方法。但是现在我尝试直接从文件中读取。什么都没有发生 - 像以前一样返回 NULL。我做错了什么?:

SELECT CONVERT(XML, BulkColumn,2) AS BulkColumn
FROM OPENROWSET(BULK 'H:\file.xml', SINGLE_BLOB) AS x;

DECLARE @yourXML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)    

SELECT @yourXML = XMLData FROM XMLwithOpenXML WHERE ID = '1' -- The row to process    

EXEC sp_xml_preparedocument @hDoc OUTPUT, @yourXML


--with OPENXML
 DECLARE @i INT;
 EXEC sp_xml_preparedocument @i output, @YourXML,'<root xmlns:dflt="http://www.bmecat.org/bmecat/1.2/bmecat_new_catalog" />';
SELECT LANGUAGE 
FROM OPENXML(@i,'/dflt:BMECAT/dflt:HEADER/dflt:CATALOG') WITH(LANGUAGE VARCHAR(MAX) 'dflt:LANGUAGE'); 

EXEC sp_xml_removedocument @hDoc
GO