Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LinqtoXML:如何删除值不在另一个集合中的节点_C#_Xml_Linq_Linq To Xml - Fatal编程技术网

C# LinqtoXML:如何删除值不在另一个集合中的节点

C# LinqtoXML:如何删除值不在另一个集合中的节点,c#,xml,linq,linq-to-xml,C#,Xml,Linq,Linq To Xml,我有一个xml文档,其中一个节点包含用户节点列表,另一个节点包含具有用户列表的组。我想从users集合中删除groups集合中没有匹配dn的所有节点 作为下面简化结构中的一个示例,我试图删除所有deleteme、user节点 <?xml version="1.0" encoding="utf-8"?> <syncdata > <users > <user> <dn>deleteme1</dn>

我有一个xml文档,其中一个节点包含用户节点列表,另一个节点包含具有用户列表的组。我想从users集合中删除groups集合中没有匹配dn的所有节点

作为下面简化结构中的一个示例,我试图删除所有deleteme、user节点

<?xml version="1.0" encoding="utf-8"?>
<syncdata >
  <users >
    <user>
      <dn>deleteme1</dn>      
    </user>
    <user>
      <dn>deleteme2</dn>      
    </user>
    <user>
      <dn>deleteme3</dn>      
    </user>
    <user>
      <dn>JohnSmith</dn>      
    </user> 
  </users>
  <groups>
  <group name="group2">     
      <users>
        <user>
          <dn>JohnSmith</dn>
        </user>
      </users>
    </group>
    <group name="group1">      
      <users>
        <user>
          <dn>JohnDoe</dn>
        </user>
        <user>
          <dn>JohnnyMorris</dn>
        </user>        
      </users>
    </group>
</groups>
  </syncdata>  

这是可能的吗?

获取两个系列的简单且更可靠的方法:

var users = xDoc.Element("syncdata").Element("users")
            .Elements("user").ToList();  // cache in list

var userNamesInGroups = xDoc.Element("syncdata").Element("groups")
           .Descendants("user").Element("dn").Value;

var usersToDelete = users
           .Where(u => ! userNamesInGroups.Contains(u.Element("dn").Value)); 

 foreach(var user in usersToDelete)
     user.Remove();

我把它扩展了一点。您可能可以将其滚动到更少的Linq语句中,但请注意ToList。你需要一个foreach来做Removesthanks,顺便问一下,有没有一种方法可以只改变一个字符就对一篇文章进行编辑?您的示例具有常量,试图将其更改为Contains,并且一次更改的字符太少
var users = xDoc.Element("syncdata").Element("users")
            .Elements("user").ToList();  // cache in list

var userNamesInGroups = xDoc.Element("syncdata").Element("groups")
           .Descendants("user").Element("dn").Value;

var usersToDelete = users
           .Where(u => ! userNamesInGroups.Contains(u.Element("dn").Value)); 

 foreach(var user in usersToDelete)
     user.Remove();
var xDoc = XDocument.Load(fname);

HashSet<string> set = new HashSet<string>(xDoc.Root.Element("groups")
                                              .Descendants("dn")
                                              .Select(dn => (string)dn));

foreach (var user in xDoc.Root.Element("users").Elements("user").ToList())
{
    if(!set.Contains(user.Element("dn").Value))
        user.Remove();
}

var newXml = xDoc.ToString();
string xml = @"<?xml version='1.0' encoding='utf-8'?>
    <syncdata >
      <users >
        <user>
          <dn>JohnDoe</dn>      
        </user>
        <user>
          <dn>deleteme2</dn>      
        </user>
        <user>
          <dn>deleteme3</dn>      
        </user>
        <user>
          <dn>JohnSmith</dn>      
        </user> 
      </users>
      <groups>
        <group name='group2'>     
          <users>
            <user>
              <dn>JohnSmith</dn>
            </user>
          </users>
        </group>
        <group name='group1'>      
          <users>
            <user>
              <dn>JohnDoe</dn>
            </user>
            <user>
              <dn>JohnnyMorris</dn>
            </user>        
          </users>
        </group>
      </groups>
    </syncdata>  ";

    var doc = XDocument.Parse(xml); 

    var groupUsersList =  doc.Root.Element("groups")
                                   .Descendants("dn")
                                   .Select(x => (string)x)
                                   .ToList();

    var users = doc.Root.Element("users").Elements("user").ToList();
    foreach (var user in users )
    {
        if(!groupUsersList.Contains(user.Element("dn").Value))
            user.Remove();
    }

    Console.WriteLine(doc.ToString());
    // prints <syncdata>
    //          <users>
    //             <user>
    //               <dn>JohnDoe</dn>
    //              </user>
    //              <user>
    //               <dn>JohnSmith</dn>
    //              </user>
    //           </users>
    //          <groups>...