删除 SQL Server 中不同级别的空 XML 标记

Posted

技术标签:

【中文标题】删除 SQL Server 中不同级别的空 XML 标记【英文标题】:Remove Varying levels of empty XML tags in SQL Server 【发布时间】:2014-09-02 16:05:09 【问题描述】:

我正在使用 FOR XML EXPLICIT 来联合将一些 SQL 表信息转换为 XML 文件。一切正常,但我在结果中有大量空标签,处于各种不同的级别。我想删除所有空标签,但保留每个组的顶层。这是我的意思的一个例子:

使用这个无意义的 XML 示例,我可以使用 .modify xquery 删除底层空节点:

DECLARE @XML XML = 
'<Whatever>
  <GlassesTypes>
      <GlassesType />
  </GlassesTypes>
  <ExpressionOfJoy>
      <FellOver>Y</FellOver>
  </ExpressionOfJoy>
  <Flights>
    <Flight>
      <Bookings>
        <Booking>
          <Segments>
            <Segment />
          </Segments>
        </Booking>
      </Bookings>
    </Flight>
  </Flights>
</Whatever>'

SELECT @XML as Before

SET  @Xml.modify('delete //*[not(node())]');

SELECT @XML AS After

这完全符合我对“GlassesTypes”的要求,但“Flights”中仍有空节点级别。我可以对每个级别重复相同的修改命令,直到只显示“航班”,但这样做会删除“GlassesTypes”空占位符:

DECLARE @XML XML = 
'<Whatever>
  <GlassesTypes>
      <GlassesType />
  </GlassesTypes>
  <ExpressionOfJoy>
      <FellOver>Y</FellOver>
  </ExpressionOfJoy>
  <Flights>
    <Flight>
      <Bookings>
        <Booking>
          <Segments>
            <Segment />
          </Segments>
        </Booking>
      </Bookings>
    </Flight>
  </Flights>
</Whatever>'

SELECT @XML as Before

SET  @Xml.modify('delete //*[not(node())]');
SET  @Xml.modify('delete //*[not(node())]');
SET  @Xml.modify('delete //*[not(node())]');
SET  @Xml.modify('delete //*[not(node())]');
SET  @Xml.modify('delete //*[not(node())]');

SELECT @XML AS After

有没有什么方法可以删除所有空节点,直到倒数第二个空节点,而不管组包含多少级别?理想的结果是这样的:

<Whatever>
  <GlassesTypes />
  <ExpressionOfJoy>
      <FellOver>Y</FellOver>
  </ExpressionOfJoy>
  <Flights />
</Whatever>

在这个例子中,只有“Whatever”标签,但在真实数据中,可能有几个重复的,都具有不同级别的信息,被根标签或等效标签所包含。

非常感谢任何帮助!

谢谢, 标记

【问题讨论】:

【参考方案1】:

您可以将您的“空”版本定义为不包含任何后代属性或文本节点,而不是不包含任何后代节点。然后通过仅选择其子代的后代来保留&lt;Whatever&gt; 的子代:

/Whatever/*//*[empty(.//text() | .//attribute())]

【讨论】:

您好,谢谢您的回答;你能澄清一下实际的脚本行是什么样的吗?对不起,我以前没有用过很多 xquery - 你稍微落后了我! @HighPlainsGrifter 这只是delete 之后的XPath,代替了//*[not(node())]。您应该只需要执行一次。 Gotcha - 我试过了,它给出了一个错误,告诉我不支持 XQuery 语法'attribute()',所以我想我一定做错了什么。但是,我特别没有在我的 XML 中使用属性,所以这很好;我已删除该位以保留“SET @XML.modify('delete /Whatever/*//*[empty(.//text())]')”,它可以完美运行。感谢您的帮助! @HighPlainsGrifter 嗯,也许attribute() 是 XSLT 2.0,不确定。如果您需要保留带有属性的元素,您可以尝试将.//attribute() 替换为.//@*,应该会支持。

以上是关于删除 SQL Server 中不同级别的空 XML 标记的主要内容,如果未能解决你的问题,请参考以下文章

sql server 查询 order by 与 union 并替换多个列的空值

Seaborn FacetGrid 包括已删除级别的空列/行

从 SQL Server 中的 XML 中删除所有空节点

sql server where 字段 is null 的问题

SQL Server 2005:读取提交事务隔离级别中的键范围锁?

使用 XSLT 删除 XML 消息中的空元素字段和默认值