如何从c#中的xml文件读取/写入节点和子节点可能使用xpath?

时间:2009-11-13 20:02:22

标签: c# xml xpath

也许有人可以帮助我。我需要两种方法。

第一个应该打开一个xml文件并获取具有给定参数的所有节点,即:

XML文件(file.xml):

<Menu id="1" Name="myMenu">
  <MenuItem Header="Header 1" Name="header1" />
  <MenuItem Header="Header 2" Name="header2">
    <MenuItem Header="subHeader 2.1" Name="header2_1">
      <MenuItem Header="subsubHeader 2.1.1" Name="header2_1_1" />
    </MenuItem>
  </MenuItem>
  <MenuItem Header="Header 3" Name="header3" />
</Menu>

所以,现在我需要用这样的方法从xml中获取值:

public static List<string, string>ReadXML(string filename, string node, string[] attributes, bool searchSubNodes);

调用方法示例:ReadXMLValues("file.xml", "MenuItem", new string[] {"Header", "Name"}, true);

这将返回两个字符串的列表,如:

"Header 1", "header1"
"Header 2", "header2"
"subHeader 2.1", "header2_1" <-- this should be in the list only if searchSubNodes is enabled!
"subsubHeader 2.1.1", "header2_1_1" <-- the same for this one!!!
"Header 3", "header3"

这是阅读部分,现在是写作部分:

filename与上面的file.xml相同。     public static void WriteXML(string filename,string node,List attributes);

现在假设file.xml有空标题属性,如下所示:

<Menu id="1" Name="myMenu">
  <MenuItem Header="" Name="header1" />
  <MenuItem Header="" Name="header2">

我需要将值放入标题中,finall结果应如下所示:

   <Menu id="1" Name="myMenu">
      <MenuItem Header="Header 1" Name="header1" />
      <MenuItem Header="Header 2" Name="header2">

这样的事可能吗??? C#大师和其他知道如何做的人请请帮助我!我不知道怎么做。

祝你好运!

3 个答案:

答案 0 :(得分:1)

您可以使用XPath进行所有搜索。

XmlNodeList nodes = doc.SelectNodes("/Menu/MenuItem");

在这种情况下,nodes将包含作为顶级MenuItem元素子元素的所有Menu元素。

XmlNodeList nodes = doc.SelectNodes("/Menu/MenuItem | /Menu/MenuItem/MenuItem");

在这种情况下,nodes将包含所有MenuItem元素,这些元素属于Menu或属MenuItem的{​​{1}}个孩子。< / p>

您还可以找到不超过1 Menu祖先的所有MenuItem个节点:

MenuItem

或者您可以找到所有XmlNodeList nodes = doc.SelectNodes("//MenuItem[count(ancestor::MenuItem) &lt; 2]"); 个节点:

MenuItem

但是,您选择选择它们,处理元素的方式相同:

XmlNodeList nodes = doc.SelectNodes("//MenuItem");

因此,这表明您可以将此方法封装为具有您建议的签名的方法:

foreach (XmlElement elm in nodes)
{
   myList.Add(new[] { elm.GetAttribute("Header"), elm.GetAttribute("Name") });
}

答案 1 :(得分:0)

编辑:

要使用XPath选择具有给定节点名称和两个给定属性的所有节点,请使用以下XPath表达式(我不知道是否有更好的方法来执行此操作,但这可行):

//NodeName[@FirstAttributeName][@SecondAttributeName]

在代码中你可以这样做(对于你的例子中的MenuItems)。我更新了代码,使您在文档中放置的命名空间以前缀“x”表示。此外,XPath表达式已更新为在节点之前使用该前缀。

XPathDocument doc = new XPathDocument("data2.xml");
XPathNavigator nav = doc.CreateNavigator();
XmlNamespaceManager mgr = new XmlNamespaceManager(nav.NameTable);
mgr.AddNamespace("default", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
XPathNodeIterator iterator = nav.Select("//default:MenuItem[@Header][@Name]", mgr);

while (iterator.MoveNext())
{
    Console.Write(iterator.Current.GetAttribute("Header", ""));
    Console.Write(iterator.Current.GetAttribute("Name", ""));
    Console.Write(Environment.NewLine);
}

=====

你必须使用XPath吗?您可以为Menu / MenuItem创建映射到XML的类,如下所示:

public class Menu
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<MenuItem> SubItems { get; set; }
}

public class MenuItem
{
    public string Header { get; set; }
    public string Name { get; set; }
    public List<MenuItem> SubItems { get; set; }
}

然后让XMLSerializer为你完成工作(它可以同时做,读,写)。之后,您可以将过滤应用于内存列表(例如,使用Linq-To-Objects)。

如果您想使用XPath执行此操作,Codeproject article可能会有所帮助。

答案 2 :(得分:0)

两种解决方案都有效。但是当搜索到的节点出现之前,就像这样:

<MenuItem x:Class="Test.Win"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/Test" <--this line make problems!
Header="Main" Name="Main">
<Menu id="1" Name="myMenu">
  <MenuItem Header="Header 1" Name="header1" />
  <MenuItem Header="Header 2" Name="header2">
    <MenuItem Header="subHeader 2.1" Name="header2_1">
      <MenuItem Header="subsubHeader 2.1.1" Name="header2_1_1" />
    </MenuItem>
  </MenuItem>
  <MenuItem Header="Header 3" Name="header3" />
</Menu>

</MyNode>

然后解决方案不起作用。如何只删除架构线或只是跳过它或类似的东西

你们中的某些人可能知道为什么以及如何解决这个问题?

问候!