选择具有特定值的子节点

Selecting a child node having specific value

我想检查“”节点 'having a specific value (say Pathankot )' 是否已经存在于特定“ 下的 xml 文件中specific Id”,然后将新的城市节点插入 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 文件所在的物理路径,将 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"));

我会创建一个扩展来稍微清理它,并使用 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 中尾随的白色 space,你可以使用 normalize-space 在 XPath 中包装 text() 调用:

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

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

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(...)。你的问题的描述听起来并不像你需要使用这些。