Linq to XML удаляет элемент, значение которого равно нулю

#.net #xml #vb.net #linq #linq-to-xml

#.net #xml #vb.net #linq #linq-to-xml

Вопрос:

У меня есть XML XElement, подобный:

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

Для того, чтобы избавиться от хитрых узлов, где значение равно нулю, я написал:

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

Который работает очень хорошо… На самом деле это работает слишком хорошо, поскольку ВСЕ узлы трюков удалены!

Что я делаю не так? Есть ли более простой способ продолжить, без лямбда-выражения?

Комментарии:

1. Я никогда не видел linq , но мне как бы интересно узнать об этой части: Value = "" ? . Разве вы не должны сравнивать это с "" , а не устанавливать на "" ? Я бы попробовал использовать это: Value == "" (Я почти уверен, что ошибаюсь).

2. В Visual Basic нет «==», но, возможно, есть «.Equals»… Я попробую, если ответа не будет. Кроме того, если вы никогда не видели Linq, зачем отвечать на вопрос Linq? LOL. кроме того: вы должны попробовать, Linq потрясающий!

3. Visual Basic на самом деле сохраняет мои нейроны в здравом уме 🙂

Ответ №1:

Это ваш полный XML-элемент или его часть? Похоже, это часть большего элемента, поскольку я не смог воспроизвести ваши результаты только с этой частью.

Если это часть большего фрагмента XML, используйте этот подход:

 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()
  

Обратите внимание, что XML заключен в <root> узлы, а <Trick> ссылка была опущена из Where метода.

Если XML такой, как вы его представили, используйте этот подход:

 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)
  

В приведенном выше примере обратите внимание, что <Play> это было опущено, поскольку это корень xml , и это <Trick> также исключено из Where метода.

Ответ №2:

Я пробовал различные решения, ни одно из них не работает! Один удаляет только 1-й найденный узел, другой выходит из строя во время выполнения…

Наконец, я придумал более простое Visual Basic Linq — БЕЗ ЛЯМБДА-решения, например:

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

Который я тестировал и который отлично работает…

Странно, насколько сложные решения радуют программистов c #!!!

Ответ №3:

Вы должны использовать оператор == или метод .Equals().

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

или

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

Ответ №4:

Чтобы увидеть, пуст ли элемент, вы можете проверить его дочерние узлы с помощью Nodes() метода, чтобы увидеть, есть ли в нем что-нибудь. Фильтруйте по пустым узлам, затем удалите их.

Обратите внимание, что в общем случае просто проверять, является ли значение пустым, неправильно, поскольку могут быть пустые дочерние элементы.

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

Поскольку вы хотели сделать это с использованием обозначения запроса (что, кстати, не имеет значения):

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