OpenXML返回NULL

时间:2018-03-14 08:10:10

标签: sql sql-server xml

我正在尝试使用Microsoft SQL Server中的OpenXML使用以下查询将xml导入我的数据库:

DECLARE @xml XML;
DECLARE @y INT;

SET @xml
    = '<ArrayOfArticle xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Article>
    <ScriptId xmlns="https://test.com/">5135399</ScriptId>
    <Title xmlns="https://test.com/">Stocks divided into two corners</Title>
    <Mediatype xmlns="https://test.com/">News papeer</Mediatype>
    <Abstract xmlns="https://test.com/">Foreign capital doubled this year.</Abstract>
    <ScriptDate xmlns="https://test.com/">2017-12-30T00:00:00</ScriptDate>
    <ScriptTypeId xmlns="https://test.com/">1</ScriptTypeId>
    <ScriptType xmlns="https://test.com/">News general</ScriptType>
    <Media xmlns="https://test.com/">Times</Media>
    <ArticleUrl xmlns="https://test.com/">http://test.com</ArticleUrl>
    <AnalysisResult xmlns="https://test.com/">
      <Analysis>
        <Regno>111</Regno>
        <Name>New York Times</Name>
        <Result>1</Result>
        <ResultName>Positive</ResultName>
      </Analysis>
      <Analysis>
        <Regno>222</Regno>
        <Name>Washington Post</Name>
        <Result>1</Result>
        <ResultName>Negative</ResultName>
      </Analysis>
    </AnalysisResult>
    <FacebookStats xmlns="https://test.com/">
      <ShareCount xsi:nil="true" />
      <LikeCount xsi:nil="true" />
      <CommentCount xsi:nil="true" />
      <TotalCount xsi:nil="true" />
    </FacebookStats>
    <MediaScore xmlns="https://test.com/">
      <MediaScore>
        <Regno>111</Regno>
        <CompanyName>New York Times</CompanyName>
        <MediaScoreID>2</MediaScoreID>
        <Name>Neither</Name>
      </MediaScore>
      <MediaScore>
        <Regno>222</Regno>
        <CompanyName>Washington Post</CompanyName>
        <MediaScoreID>2</MediaScoreID>
        <Name>Neither</Name>
      </MediaScore>
    </MediaScore>
    <Page xmlns="https://test.com/">26</Page>
    <ProgramId xmlns="https://test.com/">0</ProgramId>
    <ProgramTime xmlns="https://test.com/" xsi:nil="true" />
    <ProgramLength xmlns="https://test.com/">0</ProgramLength>
    <ProgramOrder xmlns="https://test.com/">0</ProgramOrder>
  </Article>
 </ArrayOfArticle>';

EXEC sp_xml_preparedocument @y OUTPUT, @xml;
SELECT *
FROM
    OPENXML(@y, '/ArrayOfArticle/Article', 1)
    WITH
    (
        ScriptId VARCHAR(20),
        Title VARCHAR(30),
        Mediatype VARCHAR(30)
    );

但查询只返回NULL值。我在这里错过了什么?使用SSIS导入XML是否最佳?不确定我能在给定的时间内提供多少细节。

enter image description here

3 个答案:

答案 0 :(得分:5)

请勿使用FROM OPENXML。这种方法(连同相应的SP准备和删除文档)已经过时,不应再使用了。

尝试使用XML类型的本机方法,在本例中为.value()

您的XML相当奇怪 - 与名称空间有关。如果它的创建在你的控制之下,你应该尝试清理这个命名空间。不同寻常的是,您的XML反复声明默认命名空间。

您可以将深度搜索与// 一起使用,并使用命名空间通配符*:

--GetItEasyCheesy (not recommended)
SELECT @xml.value(N'(//*:ScriptId)[1]',N'int') AS ScriptId
      ,@xml.value(N'(//*:Title)[1]',N'nvarchar(max)') AS Title
      ,@xml.value(N'(//*:Mediatype )[1]',N'nvarchar(max)') AS Mediatype ;

您可以将名称空间声明为默认名称,但在这种情况下,您必须通配外部元素,因为它们不是此名称空间的一部分:

--Use a default namespace
WITH XMLNAMESPACES(DEFAULT 'https://test.com/') 
SELECT @xml.value(N'(/*:ArrayOfArticle/*:Article/ScriptId/text())[1]',N'int') AS ScriptId
      ,@xml.value(N'(/*:ArrayOfArticle/*:Article/Title/text())[1]',N'nvarchar(max)') AS Title
      ,@xml.value(N'(/*:ArrayOfArticle/*:Article/Mediatype/text())[1]',N'nvarchar(max)') AS Mediatype;

推荐的方法是将内部命名空间绑定到前缀并使用此

--Recommended
WITH XMLNAMESPACES('https://test.com/' AS ns) 
SELECT @xml.value(N'(/ArrayOfArticle/Article/ns:ScriptId/text())[1]',N'int') AS ScriptId
      ,@xml.value(N'(/ArrayOfArticle/Article/ns:Title/text())[1]',N'nvarchar(max)') AS Title
      ,@xml.value(N'(/ArrayOfArticle/Article/ns:Mediatype/text())[1]',N'nvarchar(max)') AS Mediatype;

如果您的<ArrayOfArticles>包含多个<Article>,则可以使用.nodes()将其作为派生表获取。在这种情况下,查询是

WITH XMLNAMESPACES('https://test.com/' AS ns) 
SELECT art.value(N'(ns:ScriptId/text())[1]',N'int') AS Recommended
      ,art.value(N'(ns:Title/text())[1]',N'nvarchar(max)') AS Title
      ,art.value(N'(ns:Mediatype/text())[1]',N'nvarchar(max)') AS Mediatype
FROM @xml.nodes(N'/ArrayOfArticle/Article') AS A(art);

答案 1 :(得分:2)

您的XML包含名称空间,我使用xquery从XML中提取数据

更新,其他元素提取

    DECLARE @xml XML;
    SET @xml
        = '<ArrayOfArticle xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Article>
        <ScriptId xmlns="https://test.com/">5135399</ScriptId>
        <Title xmlns="https://test.com/">Stocks divided into two corners</Title>
        <Mediatype xmlns="https://test.com/">News papeer</Mediatype>
        <Abstract xmlns="https://test.com/">Foreign capital doubled this year.</Abstract>
        <ScriptDate xmlns="https://test.com/">2017-12-30T00:00:00</ScriptDate>
        <ScriptTypeId xmlns="https://test.com/">1</ScriptTypeId>
        <ScriptType xmlns="https://test.com/">News general</ScriptType>
        <Media xmlns="https://test.com/">Times</Media>
        <ArticleUrl xmlns="https://test.com/">http://test.com</ArticleUrl>
        <AnalysisResult xmlns="https://test.com/">
          <Analysis>
            <Regno>111</Regno>
            <Name>New York Times</Name>
            <Result>1</Result>
            <ResultName>Positive</ResultName>
          </Analysis>
          <Analysis>
            <Regno>222</Regno>
            <Name>Washington Post</Name>
            <Result>1</Result>
            <ResultName>Negative</ResultName>
          </Analysis>
        </AnalysisResult>
        <FacebookStats xmlns="https://test.com/">
          <ShareCount xsi:nil="true" />
          <LikeCount xsi:nil="true" />
          <CommentCount xsi:nil="true" />
          <TotalCount xsi:nil="true" />
        </FacebookStats>
        <MediaScore xmlns="https://test.com/">
          <MediaScore>
            <Regno>111</Regno>
            <CompanyName>New York Times</CompanyName>
            <MediaScoreID>2</MediaScoreID>
            <Name>Neither</Name>
          </MediaScore>
          <MediaScore>
            <Regno>222</Regno>
            <CompanyName>Washington Post</CompanyName>
            <MediaScoreID>2</MediaScoreID>
            <Name>Neither</Name>
          </MediaScore>
        </MediaScore>
        <Page xmlns="https://test.com/">26</Page>
        <ProgramId xmlns="https://test.com/">0</ProgramId>
        <ProgramTime xmlns="https://test.com/" xsi:nil="true" />
        <ProgramLength xmlns="https://test.com/">0</ProgramLength>
        <ProgramOrder xmlns="https://test.com/">0</ProgramOrder>
      </Article>
     </ArrayOfArticle>'

    DECLARE @T TABLE (XmlCol XML)
    INSERT INTO @T 
    SELECT @xml


    ;WITH XMLNAMESPACES ('https://test.com/' as p1)
    SELECT z.t.value ('../../p1:ScriptId[1]',' varchar(100)') ScriptId,
           z.t.value ('../../p1:Title[1]',' varchar(100)') Title,
           z.t.value ('../../p1:Mediatype[1]',' varchar(100)') Mediatype,
           z.t.value ('p1:CompanyName[1]', 'varchar(100)') CompanyName
                FROM @T t
        CROSS APPLY XmlCol.nodes ('/ArrayOfArticle/Article/p1:MediaScore/p1:MediaScore') z(t)

答案 2 :(得分:1)

DECLARE @y INT

EXEC sp_xml_preparedocument @y OUTPUT, @xml,
'<ns xmlns:x="https://test.com/"/>'

SELECT *
FROM
    OPENXML(@y, '/ArrayOfArticle/Article', 2)
    WITH
    (
        [ScriptId] VARCHAR(20) 'x:ScriptId', --<< and so on
        [Title] VARCHAR(30),
        Mediatype VARCHAR(30)
    )

EXEC sp_xml_removedocument @y  --<< lost in your code