1

問題

XML 変数を宣言し、次のように SQL クエリ内でこの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 ファイル内のすべての一重引用符を 2 つの一重引用符に置き換えてからクエリにコピーすることで、一重引用符をエスケープしようとしました。運がない。
  • アンパサンドを取り出してみましたが、うまくいかないようです。SQL によってエラーが検出された場所の近くには、特殊文字はないようです。また運がない。

質問

一重引用符は問題ではないようです。不正な文字が何であるか、これらの文字を除外する方法を正確に見つけるのに苦労しています。外部ファイルから XML ファイルをインポートし、内容を変数と同じに設定すると、コーディングを聞く代わりに問題が解決する可能性があります。これはどのように機能しますか?また、一重引用符を 2 つの一重引用符に置き換える必要があることも認識しています。私はそれをしましたが、私はまだまったく同じ問題を抱えています。問題を理解するための助けをいただければ幸いです。

システム パラメータ

  • MS SQL Server マネジメント スタジオ
  • 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;
4

1 に答える 1