【问题标题】:Selecting a child node having specific value选择具有特定值的子节点
【发布时间】:2015-04-29 06:19:57
【问题描述】:

我想检查“”节点“具有特定值(比如 Pathankot)”是否已经存在于特定“ 具有特定 Id”下的 xml 文件中, 在将新的城市节点插入 xml 之前。

< users> 
     < user Id="4/28/2015 11:29:44 PM"> 
          <city>Fazilka</city> 
          <city>Pathankot </city> 
          <city>Jalandher</city> 
          <city>Amritsar</city> 
     </user> 
</users> 

为了插入,我使用以下 c# 代码

 XDocument xmlDocument = XDocument.Load(@"C:\Users\Ajax\Documents\UserSelectedCity.xml");
        string usrCookieId = Request.Cookies["CookieId"].Value;
xmlDocument.Element("Users")
            .Elements("user")
.Single(x => (string)x.Attribute("Id") == usrCookieId)
             //Incomplete because same named cities can be entered more that once 
             //need to make delete function
            .Add(
            new XElement("city", drpWhereToGo.SelectedValue));

我的问题:

  • 我如何检查具有特定值的 节点的天气说 在插入新城市之前,xml 文件中已经存在 Pathankot 节点。
  • 我正在使用绝对路径” XDocument xmlDocument =
    XDocument.Load(@"C:\Users\Ajax\Documents\Visual Studio
    2012\WebSites\punjabtourism.com\UserSelectedCity.xml");"
    这个 不允许我在不更改的情况下将文件移动到新文件夹
    不可取的路径。但是如果我使用相对路径
    出现“拒绝访问”错误;

【问题讨论】:

    标签: c# xml linq linq-to-xml


    【解决方案1】:

    我会使用这个简单的方法:

    var query =
        xmlDocument
            .Root
            .Elements("user")
            .Where(x => x.Attribute("Id").Value == usrCookieId)
            .Where(x => !x.Elements("city").Any(y => y.Value == "Pathankot"));
    
    foreach (var xe in query)       
    {
        xe.Add(new XElement("city", drpWhereToGo.SelectedValue));
    }
    

    如果可能,最好避免使用.Single(...).First(...)。您的问题的描述听起来不像您需要使用这些。

    【讨论】:

      【解决方案2】:

      试试这个:-

      首先通过指定您的 XML 文件所在的物理路径将 XML 文件加载到 XDocument 对象中。获得对象后,只需获取具有匹配条件的 First 节点(请注意,我使用的是 First 而不是 Single cz,您可能有多个具有相同匹配条件的节点,请参阅 Single & First 之间的区别)

      XDocument xmlDocument = XDocument.Load(@"YourPhysicalPath");
      xmlDocument.Descendants("user").First(x => (string)x.Attribute("Id") == "1"
                         && x.Elements("city").Any(z => z.Value.Trim() == "Pathankot"))
                       .Add(new XElement("city", drpWhereToGo.SelectedValue));
      xmlDocument.Save("YourPhysicalPath");
      

      最后将所需的城市添加到从查询中检索到的节点并保存 XDocument 对象。

      更新:

      如果您想先检查是否满足所有条件,则只需使用Any,如下所示:-

      bool isCityPresent = xdoc.Descendants("user").Any(x => (string)x.Attribute("Id") == "1"
                        && x.Elements("city").Any(z => z.Value.Trim() == "Pathankot"));
      

      【讨论】:

      • 我可以在 If() 下使用这个表达式吗 Like 'If(xmlDocument.Descendants("user").First(x => (string)x.Attribute("Id") == "1 " && x.Descendants("city").Any(z => z.Value.Trim() == "Pathankot"))'{ //那就不要录入 }
      • @AnilKumar - 不,因为它会返回一个 XElement 而不是布尔值,如果你想先检查然后使用我更新的代码。
      • 谢谢它运作良好!你介意回答我的第二个问题吗?
      • @AnilKumar - 好的,在这种情况下,您应该使用Server.MapPath,但它只有在您的 Web 应用程序项目中已经存在所需的 XML 时才有效。
      • if (!isCityPresent){//Then Make an entry}我正在以这种方式使用它并且它的工作原理。
      【解决方案3】:

      我会创建一个扩展来清理它,并使用 XPath 进行搜索。

      public static class MyXDocumentExtensions
      {
          public static bool CityExists(this XDocument doc, string cityName)
          {
              //Contains
              //var matchingElements = doc.XPathSelectElements(string.Format("//city[contains(text(), '{0}')]", cityName));
              //Equals
              var matchingElements = doc.XPathSelectElements(string.Format("//city[text() = '{0}']", cityName));
      
              return matchingElements.Count() > 0;
          }
      }
      

      然后这样称呼它:

      XDocument xmlDocument = XDocument.Load("xml.txt");
      var exists = xmlDocument.CityExists("Amritsar");
      

      在评论中扩展您的问题,然后您可以将其用作:

      if(!xmlDocument.CityExists("Amritsar"))
      {
          //insert city
      }
      

      如果您想匹配 XML 中的尾随空格,则可以在 XPath 中使用 normalize-space 包装 text() 调用:

      var matchingElements = doc.XPathSelectElements(string.Format("//city[normalize-space(text()) = '{0}']", cityName.Trim()));
      

      【讨论】:

      • 不包含 XPathSelectElements 的定义。我必须使用任何指令或程序集引用吗?
      • 是的,需要添加:using System.Xml.XPath
      • 好吧,它工作得很好但是我们可以在更具体的约束下使用 xPath。我的意思是在上面的代码中,我们找到了所有具有指定城市名称的城市节点。但是,如果我们需要在具有特定用户 ID 的特定 下查找具有特定城市名称的城市,该怎么办
      • @AnilKumar //user[@id='user_id_here']/city[.='cityname_here']
      • matchingElements.ToList().ForEach(el => el.Value)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-30
      • 2021-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多