Didier Levy
Didier Levy

Reputation: 3453

Linq to XML remove element where value is null

I have a XML xElement like:

<Play> 
    <Trick Lead="E" Win="S" TNum="1">S3.S2.S4.SA></Trick>
    <Trick Lead="S" Win="N" TNum="2">DK.DA.D6.DQ></Trick>
    ..../...
    <Trick Lead="" Win="" TNum="7"></Trick>   
        .../...
    <Trick Lead="" Win="" TNum="13"></Trick>
</Play> 

In order to get rid of Trick nodes where value is null, I wrote:

myXmlElement.<Play>.<Trick>.Where(Function(m) m.<Trick>.Value = "").Remove()

Which works very well... Actually it works far too well, since ALL trick nodes are removed!

What do I do wrong? Is there a simpler way to proceed, without lambda expression?

Upvotes: 2

Views: 1707

Answers (4)

Jeff Mercado
Jeff Mercado

Reputation: 134591

To see if the element is empty, you can inspect its child nodes through the Nodes() method to see if it has anything. Filter by the empty nodes then remove them.

Note that in general, merely checking if the value is empty is wrong since there may be empty child elements.

''# assuming we have an XDocument with the above XML
myXmlDoc.<Play>.<Trick>.Where(Function(e) Not e.Nodes.Any).Remove()

Seeing as you wanted to do this using query notation (which by the way makes no difference):

Dim query = From e In myXmlDoc.<Play>.<Trick>
            Where Not e.Nodes.Any
            Select e
query.Remove()

Upvotes: 0

Craig
Craig

Reputation: 7076

You should use the == operator or .Equals() method.

myXmlElement.<Play>.<Trick>.Where(Function(m) m.<Trick>.Value == "").Remove()

or

myXmlElement.<Play>.<Trick>.Where(Function(m) m.<Trick>.Value.Equals(string.Empty)).Remove()

Upvotes: 0

Didier Levy
Didier Levy

Reputation: 3453

I have try the various solutions, none of them works! One only removes the 1st found node, the other one crashes at runtime...

Finally I came up with a simpler Visual Basic Linq - NO LAMBDA - solution, like this:

Dim xTricks = From x In myXmlElement.<Play>.<Trick> Where x.Value = "" Select x
xTricks.Remove()

Which I tested and which works fine...

Strange how complex solutions makes c# programers feel happyer!!!

Upvotes: 0

Ahmad Mageed
Ahmad Mageed

Reputation: 96557

Is that your complete XML element or a portion of it? It seems to be part of a larger element since I couldn't reproduce your results with just that portion.

If it's part of a larger piece of XML, use this approach:

Dim xml = <root><Play> 
    <Trick Lead="E" Win="S" TNum="1">S3.S2.S4.SA></Trick>
    <Trick Lead="S" Win="N" TNum="2">DK.DA.D6.DQ></Trick>
    <Trick Lead="" Win="" TNum="7"></Trick>   
    <Trick Lead="" Win="" TNum="13"></Trick>
</Play></root>

xml.<Play>.<Trick>.Where(Function(m) m.Value = "").Remove()

Notice that the XML is wrapped in <root> nodes and the <Trick> reference has been omitted from the Where method.

If the XML is as you presented it, use this approach:

Dim xml = <Play> 
    <Trick Lead="E" Win="S" TNum="1">S3.S2.S4.SA></Trick>
    <Trick Lead="S" Win="N" TNum="2">DK.DA.D6.DQ></Trick>
    <Trick Lead="" Win="" TNum="7"></Trick>   
    <Trick Lead="" Win="" TNum="13"></Trick>
</Play>

xml.<Trick>.Where(Function(m) m.Value = "").Remove()
Console.WriteLine(xml)

In the above sample, notice that <Play> has been omitted since it is the root of xml, and that <Trick> is also omitted from the Where method.

Upvotes: 2

Related Questions