问题
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