【问题标题】:C# Xelement not able to retrieve elementsC# Xelement 无法检索元素
【发布时间】:2013-05-22 12:55:49
【问题描述】:

我正在尝试测试 Linq 以检索 xml 文件中元素的某些值:

代码如下:

  try
        {
            XElement doc = XElement.Load(@"Z:\test.xml");

            string abc, def;


            foreach (XElement elm in doc.Descendants().Elements("test"))
            {
                abc = elm.Element("att").Value;
                def = elm.Element("title").Value;
                Console.WriteLine(abc);
                Console.WriteLine(def);
            }
        }

        catch (XmlException xe)
        {
            Console.WriteLine(xe);
        }

但这似乎并没有通过 foreach 循环。它没有给我任何错误。我已经对其进行了调试,它可以很好地读取 xml 文件。但是当它到达 foreach 循环时,它就退出了。什么原因。

我的 XML 文件的一部分:

<root xmlns:xsi="w3.org/2001/XMLSchema-instance"; xsi:noNamespaceSchemaLocation="test.xsd">
<test att="123" title="XXXX" />
<test att="2324" title="YYYY" />
</root>

【问题讨论】:

  • 它不是一个有效的 xml,它应该抛出一个异常。 xml 需要有一个根节点
  • 那不是一个有效的 xml 文件
  • 这个xml文件是有效的,只是我写了一部分给你看看它是什么样子的。当我调试时它被正确拾取。
  • @user726720 你能给出确切的xml吗?
  • @user726720 与您的编辑,问题可能是微不足道的......我不会期望找到那些;它们不是根的后代的子元素...

标签: c# .net xml linq


【解决方案1】:

首先你需要有单个根元素,否则会抛出异常:

<testRoot>
    <test att="123" title="XXXX" />
    <test att="2324" title="YYYY" />
</testRoot>

代码如下:

//Not XElement but XDocument
XDocument doc = XDocument.Load(@"D:\test\test.xml");

string abc, def;

foreach (XElement elm in doc.Descendants().Elements("test"))
{
    //Not elm.Element but elm.Attribute
    abc = elm.Attribute("att").Value;
    def = elm.Attribute("title").Value;
    Console.WriteLine(abc);
    Console.WriteLine(def);
}

【讨论】:

  • 谢谢你的作品。但是为什么在加载文件时不使用 xelement 而不是 xdocument。
  • 我真的不知道。但是您正在加载整个 xml 文档。您仍然可以将文档加载为 XElement.Load(),但是您必须使用 doc.Elements("test") 而不是 doc.Descendants().Elements("test")。我认为 Mark Gravel 解释了原因
  • XElementXDocument,IIRC 之间的最大区别在于,当使用 XDocument 时,你会得到一个 &lt;?xml version='1.0' encoding='utf-8'?&gt; 处理指令,而加载到 XElement 会导致在“文档片段”中,而不是完整的 XML 文档(即包含 xml 处理指令的 XML 文档)。
  • 另外,我认为@Adil Mammadav 在这里是正确的;您的原始代码的主要问题是您正在寻找 elements atttitle,但在您的 XML 示例中,它们是 attributes。但是,如果您的 XML 中确实有命名空间,那么@Mark Gravell 已经很好地说明了在这种情况下您需要做什么。
【解决方案2】:

首先我们要注意

foreach (XElement elm in doc.Descendants().Elements("test"))

只会找到不是根的元素,而不是根的直接子元素,但至少向下 2 层;这必须是根的后代的子元素。那么:您的元素是否至少下降了 2 个级别?如果没有:


既然你说它加载,这可能是一个命名空间问题。我猜你有类似的东西:

<foo xmlns="blahblahblah">
    ...
    <test>...</test>
</foo>

<bar:foo xmlns:bar="blahblahblah">
    ...
    <test>...</test>
</bar:foo>

在这种情况下,这些元素的名称不是test,而是blahblahblah:test。要查询它,您需要使用完整的XName

举个具体的例子:

string text = @"<foo xmlns=""blah""><test/></foo>";
var doc = XDocument.Parse(text);
var el0 = doc.Root.Element("test"); // null
XNamespace ns = "blah";
var el1 = doc.Root.Element(ns + "test"); // not null

显然您需要在代码中使用正确的命名空间,然后是.Elements(ns + "test")

【讨论】:

  • 这里是命名空间:xmlns:xsi="w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd">,是正确的标题
  • 您的答案是否适用于上述命名空间
  • 我已经编辑了我的问题以将命名空间添加到 XML 文件中,正如您在上面的解决方案中提到的那样,元素没有 ns。你能检查一下这是否可行。谢谢
  • @user726720 如果显示的 xml 是您的实际 xml,那么问题是我在顶部所说的:您显示的元素是 not 后代的子元素根元素。因此,您的查询不会返回它们是完全正确的。
猜你喜欢
  • 2013-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多