c# select 来自 XML 的属性或元素

c# select attribute or element from XML

<bookstore>
  <book>
    <bookID>100</bookID>
    <name> The cat in the hat </name>
  </book>
  <book>
    <bookID>90</bookID>
    <name> another book </name>
  </book>
  <book>
    <bookID>103</bookID>
    <name> a new book </name>
  </book>
</bookstore>

我正在尝试从 XML document.The 方法中选择 bookID 值,我目前使用的是 Element(bookID).Value 但有时 bookID 作为书的属性出现,如下所示:<book bookID=100> 有没有办法在 C# 中做到这一点,比如 xPath 表达式?非常感谢!

这是否需要是 XPath 表达式,或者您可以将 LinqXDocument 系统一起使用。

例如。

var xDocument = XDocument.Parse(@"<bookstore>
                                <book>
                                <bookID>100</bookID>
                                <name> The cat in the hat </name>
                                </book>
                                <book bookID=""90"">
                                <name> another book </name>
                                </book>
                                <book>
                                <bookID>103</bookID>
                                <name> a new book </name>
                                </book>
                                </bookstore>");

foreach (var xBook in xDocument.Descendants("book"))
{
    var bookIdNode = xBook.Elements("bookID").FirstOrDefault();
    int bookId = 0;

    ///there is a book id as an element
    if (bookIdNode != null)
    {
        //invalid book id.. should be an int
        if (!int.TryParse(bookIdNode.Value, out bookId))
            continue;
    }
    else
    {
        var bookIdAttr = xBook.Attributes("bookID").FirstOrDefault();
        if (bookIdAttr == null || !int.TryParse(bookIdAttr.Value, out bookId))
            continue;
    }

    if (bookId == 0)
        continue;

    //else we got our book id

}

这段代码很简单,就是枚举元素名book的后代。它首先检查是否有一个名为 bookID 的元素(区分大小写)。如果存在,它会尝试使用 int.TryParse().

方法将图书 ID 解析为 int

如果没有 bookID 元素,它接下来会检查是否有任何名称为 bookID 的属性,并使用 FirstOrDefault() 扩展方法获取第一个实例(或 null)。如果存在 bookID 属性的实例,它还会尝试使用 int.TryParse() 方法解析 int。

在这个小片段的末尾,我们检查 bookId 是否为 0 如果它为零,我们可以假设出现了问题。然而,这不应该发生,因为逻辑应该继续枚举并忘记没有 bookID 元素或 bookID 属性的元素。

在 XPath 中,您可以使用联合 (|) 运算符来组合 return 不同部分的查询 XML。例如:

//book/bookID/text() | //book/@bookID

以上 XPath returns 文档顺序中 bookID 元素和 bookID 属性的文本内容。请参阅使用 XmlDocument.SelectNodes() 执行 XPath 的演示。

Demo Codes :

var xml = @"<bookstore>
  <book>
    <bookID>100</bookID>
    <name> The cat in the hat </name>
  </book>
  <book bookID='90'>
    <name> a new book </name>
  </book>
  <book>
    <bookID>103</bookID>
    <name> another book </name>
  </book>
</bookstore>";
var doc = new XmlDocument();
doc.LoadXml(xml);
var result = doc.SelectNodes("//book/bookID/text() | //book/@bookID");
foreach (XmlNode r in result)
{
    Console.WriteLine(r.Value);
}

输出:

100
90
103