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

时间:2015-10-16 13:34:54

标签: sql xml import openxml

为什么在尝试将XML文档(下面的文件示例)读入SQL Server时会获得NULL值?我认为它是由于阅读文件。 SQL的第一部分似乎没问题 - 我在SQLSERVER网格中看到了xml文件。但不知道,如何读取数据。想法是 - 我想将XML文件导入SQL SERVER,使用简单的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>

  

2 个答案:

答案 0 :(得分:1)

原始文件的Thx。我把它装下来,可以毫无问题地阅读:试试这样:

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示例(包含或不包含名称空间)后,您可以比较并找到所需的最佳方法。只需将其粘贴到一个空的查询窗口中并执行:

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'  )

答案 1 :(得分:1)

是的,您的示例有效。两种方法。但现在我尝试直接从文件中读取。什么都没发生 - 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