xml 节点未处理空节点

xml nodes isn't handling an empty node

我正在尝试在 SQL Server 2019 中创建一个存储过程以将 html 解析为节点。我已经设法去除了干扰的 html,但现在我遇到了空 td 节点的问题。

这是我用来测试的字符串(注意 <td/>):

<table>
    <tr> 
        <td>Element</td>
        <td>20562</td>
        <td>20471</td>
    </tr>
    <tr>
         <td>Other</td>
         <td>No</td>
         <td>Yes</td>
    </tr>
    <tr>
         <td>Other Unique Terms</td>
         <td/>
         <td>Of note:  blah blah. </td>
    </tr>
</table>

这是我的 T-SQL:

DECLARE @data TABLE
        (
               FieldName VARCHAR(MAX),
               OldValue VARCHAR(MAX),
               NewValue VARCHAR(MAX)
        )

DECLARE @html varchar(max), @html2 xml;

SET @html = '<table><tr><td>Element</td><td>20562</td><td>20471</td></tr><tr><td>Other</td><td>No</td><td>Yes</td></tr><tr><td>Other Unique Terms</td><td/><td>Of note:  blah blah. </td></tr></table>';

SET @html2 = CAST(@html as xml);

INSERT INTO @data
    SELECT
        n.value('(./td/text())[1]', 'VARCHAR(MAX)') AS FieldName,
        n.value('(./td/text())[2]', 'VARCHAR(MAX)') AS OldValue,
        n.value('(./td/text())[3]', 'VARCHAR(MAX)') AS NewValue
    FROM 
        @html2.nodes('/table/tr') AS nodes(n) 

SELECT *
FROM @data;

我的结果(最后一行,OldValue 应该是 NULL,NewValue 应该有文本):

FieldName              OldValue                 NewValue
---------------------------------------------------------
Element                20562                    20471
Other                  No                       Yes
Other Unique Terms     Of note:  blah blah.     NULL

我该如何解决这个问题?

试试看:

SELECT
    n.value('td[1]/text()[1]', 'VARCHAR(MAX)') AS FieldName,
    n.value('td[2]/text()[1]', 'VARCHAR(MAX)') AS OldValue,
    n.value('td[3]/text()[1]', 'VARCHAR(MAX)') AS NewValue
FROM 
    @html2.nodes('/table/tr') AS nodes(n) ;

简而言之:

  • 看起来,好像总有三个<td>个元素。
  • 他们的位置说明了他们的意义
  • 因此我们先阅读 <td> 并选择其文本。
  • 然后我们读第二 ...等等...
  • 最后的 [1] 告诉引擎选择 first text() 节点,它强制执行所需的 singleton 值.

或者你可以试试这个

SELECT
    n.value('td[1]', 'VARCHAR(MAX)') AS FieldName,
    n.value('td[2]', 'VARCHAR(MAX)') AS OldValue,
    n.value('td[3]', 'VARCHAR(MAX)') AS NewValue
FROM 
    @html2.nodes('/table/tr') AS nodes(n) 

在这种情况下,空元素将作为空字符串而不是 NULL 返回。

这对我有用:

SELECT
    n.value('(./td/text())[1]', 'VARCHAR(MAX)') as FieldName,
    n.value('(./td)[2]', 'VARCHAR(MAX)') as OldValue,
    n.value('(./td)[3]', 'VARCHAR(MAX)') as NewValue
FROM @html2.nodes('/tr') as nodes(n);

我删除了 table。因为我知道第一列不能为空,所以我为此保留了 text()。