在SQL中声明XML变量时的非法XML字符

时间:2016-04-08 19:04:05

标签: sql sql-server xml illegal-characters

问题

我正在尝试声明一个XML变量,并在我的SQL查询中将其设置为this XML文件,如下所示:DECLARE @x XML = 'xml content here';。 但是,当我尝试使用当前的XML文件执行此操作时,我会在屏幕上显示此错误消息:

Msg 9420, Level 16, State 1, Line 1 XML parsing: line 1132, character 265, illegal xml character

我已经尝试解决这个问题

  • 我试图通过用两个单引号替换XML文件中的所有单引号然后复制到查询中来逃避单引号。没运气。
  • 我尝试取出&符号,但这似乎不起作用。在SQL检测到错误的位置附近,似乎没有任何特殊字符。再没有运气了。

问题

在我看来,单引号不是问题。我无法确切地找到非法字符是什么,我如何过滤掉这些字符。也许从外部文件导入XML文件并将内容设置为等于变量而不是听到编码它将解决问题。这怎么样?我也知道单引号必须用两个单引号代替。我做到了,但我仍然有同样的问题。任何理解这个问题的帮助都表示赞赏。

系统参数

  • MS SQL Server Management Studio
  • Windows Server 2012 R2标准版

完整代码

这是我正在执行的完整代码,它给了我错误:

DECLARE @x XML = ' copy xml file here... ';

With MyPersonCTE AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS PersonID
          ,p.value('FirstName[1]','varchar(max)') AS FirstName
          ,p.value('LastName[1]','varchar(max)') AS LastName
          ,p.value('Biography[1]','varchar(max)') AS Biography
          ,p.value('Expertise[1]','varchar(max)') AS Expertise
          ,p.value('Image[1]','varchar(max)') AS Image
          ,p.value('Link[1]','varchar(max)') AS Link
          ,p.query('Books') AS BookNode
          ,p.query('Articles') AS ArticleNode
          --same for Papers, Artwork...
    FROM @x.nodes('/People/Person') AS A(p) 
)
,MyBooksCTE AS
(
    SELECT MyPersonCTE.*
          ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS BookID
          ,x.value('Year[1]','int') AS BookYear
          ,x.value('Details[1]','varchar(max)') AS BookDetails
    FROM MyPersonCTE
    CROSS APPLY MyPersonCTE.BookNode.nodes('/Books/Book') A(x)  
)
,MyArticlesCTE AS
(
    SELECT MyPersonCTE.*
          ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS ArticleID
          ,x.value('Year[1]','int') AS ArticleYear
          ,x.value('Details[1]','varchar(max)') AS ArticleDetails
    FROM MyPersonCTE
    CROSS APPLY MyPersonCTE.ArticleNode.nodes('/Articles/Article') A(x)  
)
--same for Papers, Artwork...
SELECT p.*
      ,b.BookID
      ,b.BookYear
      ,b.BookDetails
      ,a.ArticleID
      ,a.ArticleYear
      ,a.ArticleDetails  
INTO #tempAllData
FROM MyPersonCTE AS p
LEFT JOIN MyBooksCTE AS b ON p.PersonID=b.PersonID
LEFT JOIN MyArticlesCTE AS a ON p.PersonID=a.PersonID ;

--#tempAllData is now filled with all data, copied in all combination: much to much
--but DISTINCT is your friend
--in this case you'd use the PersonID as FK in all related tables

SELECT DISTINCT PersonID,FirstName,LastName,Biography,Expertise --other fields
FROM #tempAllData;

SELECT DISTINCT PersonID,BookID,BookYear,BookDetails
FROM #tempAllData;

SELECT DISTINCT PersonID,ArticleID,ArticleYear,ArticleDetails
FROM #tempAllData;

DROP TABLE #tempAllData;

1 个答案:

答案 0 :(得分:4)

看,这是重现错误的简化示例

在这个片段中你有两倍的名字“奥布莱恩”,其中“制造麻烦 在这里“体验身体的温暖促进人际关系的温暖”开幕式和闭幕式的问题是有问题的

DECLARE @x XML=
'<?xml version="1.0" encoding="UTF-8"?>
<People>
<Person>
    <FirstName>Katherine</FirstName>
    <LastName>Corker</LastName>
    <Articles>
                <Article>
            <Year></Year>
            <Details><![CDATA[<p>Corker, K. S., Lynott, D., Wortman, J., Connell, L., Donnellan, M. B., Lucas, R. E., & O’Brien, K. (2014). High quality direct replications matter: Response to Williams (2014). Social Psychology, 45, 324-326. Available <a href="https://www.academia.edu/attachments/35015451/download_file?st=MTQxMzMwNDE0MiwxMzguMjguOS4xNjEsMjEzMTg%3D&s=work_strip">here.</a></p>
<p>Lynott, D., Corker, K. S., Wortman, J., Connell, L., Donnellan, M. B., Lucas, R. E., & O’Brien, K. (2014). Replication of “Experiencing physical warmth promotes interpersonal warmth” by Williams & Bargh (2008, Science). Social Psychology, 45, 216-222. Available <a href="https://www.academia.edu/attachments/33247494/download_file?st=MTQxMzMwNDE0MiwxMzguMjguOS4xNjEsMjEzMTg%3D&s=work_strip">here.</a></p>]]></Details>
        </Article>
            </Articles>
</Person>
</People>';
SELECT @x;

现在只需改变这个

'<?xml version="1.0" encoding="UTF-8"?>

到此(不要忘记开头的“N”强制这个为Unicode)

N'<?xml version="1.0" encoding="UTF-16"?>

但是试试这个:

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

有了这个,你不必费心去讨论,只需从磁盘上的某个位置读取文件......