简体   繁体   English

如何获得xml节点的同级

[英]How to get the sibling of an xml node

I have an xml file as below 我有一个如下的xml文件

<Games>
   <Game>
      <name>Tzoker</name>
      <file>tzoker1</file>
   </Game>
   <Game>
      <file>lotto770</file>
   </Game>
   <Game>
      <name>Proto</name>
      <file>proto220</file>
   </Game>
</Games>

I want to get the values of name and file items for every Game node. 我想获取每个Game节点的名称和文件项的值。 It is easy by using this query. 使用此查询很容易。

string query = String.Format("//Games/Game");
 XmlNodeList elements1 = xml.SelectNodes(query);
 foreach (XmlNode xn in elements1)
 {
   s1 = xn["name"].InnerText;
   s2 = xn["file"].InnerText;
 }

The problem is that there are some nodes that they don't have the name item. 问题是有些节点没有名称项。 So the code above doesn't work. 因此,上面的代码不起作用。 I have solved the problem by using the following code 我已经通过使用以下代码解决了这个问题

string query = String.Format("//Games/Game/name");
XmlNodeList elements1 = xml.SelectNodes(query);
foreach (XmlNode xn in elements1)
{
  s1 = xn.InnerText;
  string query1 = String.Format("//Games/Game[name='{0}']/file", s1);
  XmlNodeList elements2 = xml.SelectNodes(query1);
  foreach (XmlNode xn2 in elements2)
  {
    s2 = xn2.InnerText;
  }
}

The problem is that there is a case that two or more nodes have the same name value. 问题是存在两个或多个节点具有相同名称值的情况。 So, the s2 variable will get the file value of the last node that the loop finds. 因此,s2变量将获取循环找到的最后一个节点的文件值。 So, I would like to find a way to get the sibling file value of the current name item. 因此,我想找到一种方法来获取当前名称项的同级文件值。 How could I do it? 我怎么能这样做? I try do move to the parent node of the current node and then to move to the file item but without success by using the following code. 我尝试通过使用以下代码来移动到当前节点的父节点,然后再移动到文件项,但是没有成功。

string query = String.Format("//Games/Game/name");
XmlNodeList elements1 = xml.SelectNodes(query);
foreach (XmlNode xn in elements1)
{
   s1 = xn.InnerText;
   string query1 = String.Format("../file");
   XmlNodeList elements2 = xml.SelectNodes(query1);
   foreach (XmlNode xn2 in elements2)
   {
     s2 = xn2.InnerText;
   }
}

I hope there is a solution. 我希望有一个解决方案。

If I understand you correctly you want to find all games that have a name. 如果我对您的理解正确,那么您想查找所有具有名称的游戏。 You can do that using XPath. 您可以使用XPath做到这一点。 Here is a solution that uses LINQ to XML. 这是使用LINQ to XML的解决方案。 I find that easier to work with than XmlDocument : 我发现它比XmlDocument更容易使用:

var xDocument = XDocument.Parse(xml);
var games = xDocument
  .Root
  .XPathSelectElements("Game[child::name]")
  .Select(
    gameElement => new {
      Name = gameElement.Element("name").Value,
      File = gameElement.Element("file").Value
    }
  );

The XPath to select all <Game> elements that have a <name> child element is Game[child::name] . 选择所有具有<name>子元素的<Game>元素的XPath是Game[child::name]

You can use Game[name] to filter Game elements to those with child element name . 您可以使用Game[name]Game元素过滤为具有child元素name元素。 This is possible because child:: is the default axes which will be implied when no explicit axes mentioned. 这是可能的,因为child::是默认轴,当未提及显式轴时将隐含默认轴。 Extending this further to check for child element file as well, would be as simple as Game[name and file] : 进一步扩展它以检查子元素file ,就像Game[name and file]一样简单:

string query = String.Format("//Games/Game[name]");
XmlNodeList elements1 = xml.SelectNodes(query);
foreach (XmlNode xn in elements1)
{
   s1 = xn["name"].InnerText;
   s2 = xn["file"].InnerText;
}

Now to answer your question literally, you can use following-sibling:: axes to get sibling element that follows current context element. 现在从字面上回答您的问题,您可以使用following-sibling::轴获取紧随当前上下文元素的兄弟姐妹元素。 So, given the context element is name , you can do following-sibling::file to return the sibling file element. 因此,如果上下文元素是name ,则可以执行following-sibling::file返回同级file元素。


Your attempt which uses ../file should also work. 您尝试使用../file尝试也应该起作用。 The only problem was, that your code executes that XPath on xml , the XmlDocument , instead of executing it on current name element : 唯一的问题是,您的代码在xml上执行了XPath,即XmlDocument ,而不是在当前name元素上执行了它:

XmlNodeList elements2 = xn.SelectNodes("../file");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM