Remove Varying levels of empty XML tags in SQL Server

天涯浪子 提交于 2019-12-11 07:44:41

问题


I am using FOR XML EXPLICIT to union to convert some SQL table info into an XML file. It's all working, but I have loads of empty tags in the results, at all sorts of different levels. I would like to remove all the empty tags, but keep the top level for each group. Here's an example of the sort of thing I mean:

Using this example bit of nonsense XML, I can remove the bottom level empty nodes with a .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

This has done exactly what I want with 'GlassesTypes', but there are still levels of empty nodes in 'Flights'. I could repeat the same modify command over and over for each level to get up to the point where only 'Flights' is displayed, but doing so will delete the 'GlassesTypes' empty placeholder:

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

Is there any way in which I can delete all empty nodes, until the penultimate empty node, regardless of how many levels a group contains? The ideal result would be this:

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

In this example, there is only 'Whatever' tag, but in the real data, there might be several repeated, all with different levels of information, encompassed by a root tag or equivalent.

Any help much appreciated!

Thanks, Mark


回答1:


You can define your version of "empty" as not containing any descendant attribute or text nodes, instead of as not containing any descendant nodes. Then retain children of <Whatever> by only selecting descendants of its children:

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


来源:https://stackoverflow.com/questions/25627732/remove-varying-levels-of-empty-xml-tags-in-sql-server

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!