如何查找缺少特定子节点的XML节点?

时间:2016-04-06 18:27:25

标签: c# .net xml linq linq-to-xml

此MSDN页面显示了如何使用Linq-to-XML查找包含某个子节点的XML节点。不幸的是,我遇到了相反的问题:我有一个很大的列表,其中一些节点缺少应该存在的某个子节点。有没有找到它们的好方法?

例如:

<Objects>
  <Object>
    <ID>1</ID>
    <A>1</A>
    <B>1</B>
    <C>1</C>
  </Object>
  <Object>
    <ID>2</ID>
    <A>2</A>
    <B>2</B>
    <C>2</C>
  </Object>
  <Object>
    <ID>3</ID>
    <A>3</A>
    <C>3</C>
  </Object>
  <Object>
    <ID>4</ID>
    <A>4</A>
    <B/>
    <C>4</C>
  </Object>
</Objects>

如何设置代码以查找缺少<Object>节点的所有<B>元素,这些元素将返回#3,但不会返回#4?

2 个答案:

答案 0 :(得分:2)

这是有效的,因为如果XContainer.Element("elementName")不存在,null会返回elementName(注意:我将您的xml复制到名为xml的字符串中,因此您需要只需.Descendents上的XDocument

    static void Main(string[] args)
    {
        var elementsWithoutB = XDocument.Parse(xml)
                               .Descendants("Object")
                               .Where(x => x.Element("B") == null);

        // Prove it works by printing the elements returned
        foreach (var element in elementsWithoutB)
        {
            Console.WriteLine(element.ToString());
        }

        Console.Read();
    }

答案 1 :(得分:1)

这是另一种解决方法,如果你想在这种情况下使用XPath,你也可以使用以下方法:

static void Main(string[] args)
        {
            XElement objects = XElement.Parse(@"<Objects>
                                                  <Object>
                                                    <ID>1</ID>
                                                    <A>1</A>
                                                    <B>1</B>
                                                    <C>1</C>
                                                  </Object>
                                                  <Object>
                                                    <ID>2</ID>
                                                    <A>2</A>
                                                    <B>2</B>
                                                    <C>2</C>
                                                  </Object>
                                                  <Object>
                                                    <ID>3</ID>
                                                    <A>3</A>
                                                    <C>3</C>
                                                  </Object>
                                                  <Object>
                                                    <ID>4</ID>
                                                    <A>4</A>
                                                    <B/>
                                                    <C>4</C>
                                                  </Object>
                                                </Objects>");

            string xpath_string = "//Object[count(B) = 0]"; //you can change the name of the element anytime,
                                                            //even in the run-time also... just make sure
                                                            //to add `System.Xml.XPath` to utilize the XPath...

            IEnumerable<XElement> query_for_objects = objects.XPathSelectElements(xpath_string);

            foreach (XElement ele in query_for_objects)
            {
                Console.WriteLine(ele.ToString());
            }
            Console.ReadKey();

在这种情况下使用XPath有什么好处,即使在运行时也可以使用自定义查询,而根本不需要更改代码!