C# 从xml属性中获取值

4

如何使用C#正确获取属性“action”和“filename”的值?

XML:

<?xml version="1.0" encoding="utf-8" ?>
 <Config version="1.0.1.1" >
   <Items>
    <Item action="Create" filename="newtest.xml"/>
    <Item action="Update" filename="oldtest.xml"/>   
  </Items>
 </Config>

C#: 我无法获取属性值,也不知道如何在foreach循环中获取值。如何解决这个问题?

        var doc = new XmlDocument();
        doc.Load(@newFile);
        var element = ((XmlElement)doc.GetElementsByTagName("Config/Items/Item")[0]); //null
        var xmlActions = element.GetAttribute("action"); //cannot get values
        var xmlFileNames= element.GetAttribute("filename"); //cannot get values

         foreach (var action in xmlActions)
         {
           //not working
         }

         foreach (var file in xmlFileNames)
         {
           //not working
         }

你的代码示例对我很有帮助。谢谢!


1
你可能需要研究一下LINQ to XML。它使得处理XML变得更加容易。 - Corak
4个回答

9
你可以使用LINQ to XML。以下查询返回具有ActionFileName属性的强类型项目集合:
var xdoc = XDocument.Load(@newFile);

var items = from i in xdoc.Descendants("Item")
            select new {
               Action = (string)i.Attribute("action"),
               FileName = (string)i.Attribute("fileName")
            };

foreach (var item in items)
{
   // use item.Action or item.FileName
}

变量items = for i in xdoc.Descendants("Item") select new { Action = (string)i.Attribute("action"), FileName = (string)i.Attribute("fileName") }; 不是正确的代码语法。 - user235973457
@user235973457 抱歉,打错了。应该是使用 from 而不是 for - Sergey Berezovskiy

3

GetElementsByTagName只会找到你直接子元素。参数应该是一个标签名,而不是整个元素路径。

如果你想要在整个文档中搜索并提供XPath表达式,请使用SelectNodes

对于您的文档,应该像这样:

var element = (XmlElement)doc.SelectNodes("/Config/Items/Item")[0];

我尝试过使用SelectNode,但不确定如何在代码中使用它。您能否给我一个示例代码? - user235973457
@user235973457:我已经添加了示例调用;我现在不能尝试它,但是我希望命名空间没有问题。如果您遇到任何错误,请包括精确的错误信息,我或其他人会稍后尝试解决。 - O. R. Mapper
@user235973457:你的意思是 XmlActions 只包含一个元素吗?这是预期的,因为 GetAttribute 只会返回一个属性节点。如果你实际上想要获取“所有 action 属性为...的节点”,那么需要遍历 SelectNodes 的结果(即 <Item> 元素的集合),并从每个 <Item> 元素中检索 actionfile 属性。 - O. R. Mapper

2

您可以使用LINQ to XML来实现您所需的功能:

// For each element that is a child of your Items element that is named Item
foreach (var item in XElement.Load("file.xml").Descendants("Items").Elements("Item"))
{
    // If the element does not have any attributes
    if (!item.Attributes().Any())
    {
        // Lets skip it
        continue;
    }

    // Obtain the value of your action attribute - Possible null reference exception here that should be handled
    var action = item.Attribute("action").Value;
    // Obtain the value of your filename attribute - Possible null reference exception here that should be handled
    var filename = item.Attribute("filename").Value;

    // Do something with your data
    Console.WriteLine("action: {0}, filename {1}", action, filename);
}

2

以下是问题的代码:

1.您在GetElementsByTagName中使用XPath,请改用标记。 2.使用[0]仅获取XmlNodeCollection中的第一个XmlNode。 3.由于只有一个XmlNode,因此获取属性时仅获得字符串结果,而不是字符串集合,然后尝试枚举。 4.foreach循环存在问题,没有针对结果对象的类型。

这是一个可行的片段:

var doc = new XmlDocument();
doc.Load("test.xml");
var items = doc.GetElementsByTagName("Item");

var xmlActions = new string[items.Count];
var xmlFileNames = new string[items.Count];
for (int i = 0; i < items.Count; i++) {
    var xmlAttributeCollection = items[i].Attributes;
    if (xmlAttributeCollection != null) {
        var action = xmlAttributeCollection["action"];
        xmlActions[i] = action.Value;

        var fileName = xmlAttributeCollection["filename"];
        xmlFileNames[i] = fileName.Value;
    }
}

foreach (var action in xmlActions) {
    //working
}

foreach (var file in xmlFileNames) {
    //working
}

或者,如果你在执行操作之前不需要将集合中的所有操作和文件名都列出来,那么你可以在for循环中直接对每个操作/文件名进行操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接