简体   繁体   English

使用LINQ在文档C#中的特定点插入新XML数据

[英]Inserting new XML Data at specific Point in document C# Using LINQ

Hello everyone I have been searching all day looking for a way to add data into a existing XML document using LINQ. 大家好,我整天都在寻找可以使用LINQ将数据添加到现有XML文档中的方法。 All that I can seem to find is how to create new elements and how to add them to just the end of the file if you will. 我似乎只能找到如何创建新元素以及如何将它们添加到文件末尾。 I am trying to create an application that will allow me to add FTP accounts and update existing ones from Filezilla Ftp client without manually having to do so. 我正在尝试创建一个应用程序,该应用程序允许我添加FTP帐户并从Filezilla Ftp客户端更新现有帐户,而无需手动执行。 Here is the XML document. 这是XML文档。

    <FileZillaServer>
  <Settings>
    <Item name="Admin port" type="numeric">14147</Item>
  </Settings>
  <Groups />
  <Users>
    <User Name="ServerManager">
      <Option Name="Pass">6</Option>
      <Option Name="Group">
      </Option>
      <Option Name="Bypass server userlimit">0</Option>
      <Option Name="User Limit">0</Option>
      <Option Name="IP Limit">0</Option>
      <Option Name="Enabled">1</Option>
      <Option Name="Comments">
      </Option>
      <Option Name="ForceSsl">0</Option>
      <IpFilter>
        <Disallowed />
        <Allowed />
      </IpFilter>
      <Permissions>
        <Permission Dir="C:\Dayz Server Manager">
          <Option Name="FileRead">1</Option>
          <Option Name="FileWrite">1</Option>
          <Option Name="FileDelete">1</Option>
          <Option Name="FileAppend">1</Option>
          <Option Name="DirCreate">1</Option>
          <Option Name="DirDelete">1</Option>
          <Option Name="DirList">1</Option>
          <Option Name="DirSubdirs">1</Option>
          <Option Name="IsHome">1</Option>
          <Option Name="AutoCreate">0</Option>
        </Permission>
        <Permission />
      </Permissions>
      <SpeedLimits DlType="0" DlLimit="10" ServerDlLimitBypass="0" UlType="0" UlLimit="10" ServerUlLimitBypass="0">
        <Download />
        <Upload />
      </SpeedLimits>
    </User>
  </Users>
</FileZillaServer>

I have so far been able to figure out how to get into the correct place of the document using a LINQ query but not really sure how to add to it. 到目前为止,我已经能够弄清楚如何使用LINQ查询进入文档的正确位置,但是还不确定如何添加到文档中。 Any help would be greatly appreciated. 任何帮助将不胜感激。 Below is the Query I'm using to get me in the right place. 以下是我用来使我处于正确位置的查询。

                var InsHere = from name in doc.Descendants("Users")
                           where name.Element("User").Attribute("Name").Value == "ServerManager"
                           select name.Element("User").Element("Permissions")
                           .Element("Permission").Attribute("Dir").Value;

So in this case what I'm needing to do is would be add another directory to the for a specific user that will change on a consistent basis. 因此,在这种情况下,我需要为特定用户添加另一个目录,该目录将不断变化。 Many situations will require that I create a whole new user. 很多情况下,我需要创建一个全新的用户。 Thank you in advance for any help. 预先感谢您的任何帮助。

Okay so after looking at the examples and the answers given I think I have begin to get closer. 好吧,在查看示例和给出的答案之后,我想我已经越来越近了。 However I am still getting either a "Parent is Missing" Exception or "Object reference" Error. 但是,我仍然收到“父项丢失”异常或“对象引用”错误。 Here is the code below that I am using to try and insert. 这是我用来尝试插入的以下代码。

            try
        {

            XDocument doc = XDocument.Load("C:/users/vildez/desktop/test.xml");

            XElement test = new XElement("TEST", "this is data");

            var InsertPoint = from user in doc.Descendants("Users")
                              where user.Element("User").Attribute("Name").Value == "ServerManager"
                              select user.Element("User").Element("Permissions").Element("Permission").Name;

            foreach (var v in InsertPoint)
            {
                XElement Perm = doc.Element(v.ToString());
                Perm.AddAfterSelf(test);
            }

            doc.Save("C:/users/vildez/desktop/123.xml");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            Application.Exit();
        }

If you are trying to add a new permission element you can use AddAfterSelf (see: http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(System.Xml.Linq.XNode.AddAfterSelf);k(AddAfterSelf);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5);k(DevLang-csharp)&rd=true ). 如果您尝试添加新的权限元素,则可以使用AddAfterSelf(请参阅: http : //msdn.microsoft.com/query/dev11.query? appId=Dev11IDEF1&l=EN-US&k=k(System.Xml.Linq.XNode .AddAfterSelf); k(AddAfterSelf); k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5); k(DevLang-csharp)&rd = true )。 Your Linq would have to change to remove the .Attribute("Dir").Value 您的Linq必须进行更改以删除.Attribute(“ Dir”)。Value

If you are trying to and a second "Dir" attribute, you can't do that. 如果尝试添加第二个“ Dir”属性,则不能这样做。 XML attributes should be unique. XML属性应该是唯一的。

--Response to comment-- -回应评论-

"... I am not trying to create another Attribute but another Element that will basically clone the one's before it and just different directory paths etc" “ ...我不是在尝试创建另一个属性,而是创建另一个元素,它将基本上克隆之前的那个属性以及只是不同的目录路径等”

Sounds like you want to add an additional Permission element with a modified directory attribute. 听起来您想添加具有修改后的目录属性的其他Permission元素。

var InsHere = from name in doc.Descendants("Users")
              where name.Element("User").Attribute("Name").Value == "ServerManager"
              select name.Element("User").Element("Permissions").Element("Permission");
var newElement = new XElement(InsHere); // this clones the found Permission element
newElement.Attribute("Dir").Value = "the new directory path to add";
InsHere.AddAfterSelf(newElement);

See if that accomplishes what you desire. 看看是否满足您的要求。

Just think about it systematically. 只需系统地考虑一下即可。 What does it take to add an xml element to a specific xml element in a document? 将xml元素添加到文档中的特定xml元素需要做什么?

  1. Find the xml element you want to add to. 找到要添加到的xml元素。
  2. Get/Create the xml element you want to add. 获取/创建要添加的xml元素。
  3. Add the xml element. 添加xml元素。

So what does that mean in this document? 那么,在本文档中这意味着什么呢?

  1. Find the user you wish to add to. 查找您要添加到的用户。 If found: 如果找到:
  2. Create the new permission. 创建新的权限。
  3. Add the new permission to the Permissions element for the user. 将新权限添加到用户的Permissions元素。
public XElement AddDirectoryPermissionForUser(XDocument doc, string userName, string dir)
{
    // I prefer using xpath queries over full linq queries
    var xpath = String.Format("//User[@Name='{0}']", userName);
    var user = doc.XPathSelectElement(xpath); // 1
    if (user != null)
    {
        var permission = CreatePermissionForDir(dir); // 2
        user.Element("Permissions").Add(permission); // 3
        return permission;
    }
    return null;
}

I'm not sure what it is you're doing exactly but this should give you a nice starting point on how to proceed. 我不确定您到底在做什么,但这应该为您提供一个良好的起点。

You can add an XElement onto, before, after any other XElement. 您可以任何其他XElement 之前,之后添加XElement。

A demonstration of adding/adjusting an option based on your query: 基于您的查询添加/调整选项的演示:

string userName = "ServerManager";
string directory = "some directory";
string optionName = "FileRead";
int optionSetting = 1;

XElement doc = XElement.Load("C:/users/vildez/desktop/test.xml");

XElement user = doc.Descendants("User")
                   .FirstOrDefault(user => 
                      user.Attribute("Name").Value == userName);

// Add user if it doesn't exist
if (user == null)
{
    XElement users = doc.Element("Users");
    if (users == null)
        doc.Add(users = new XElement("Users"));
    users.Add(user = new XElement("User",
        new XAttribute("Name", userName)));
}

XElement permission = user.Descendants("Permission")
                          .FirstOrDefault(perm => 
                          perm.Attribute("Dir").Value == directory);

// Add permission if it doesn't exist
if (permission == null)
{
    XElement permissions = user.Element("Permissions");
    if (permissions == null)
        user.Add(permissions = new XElement("Permissions"));
    permissions.Add(permission = new XElement("Permission",
        new XAttribute("Dir", directory)));
}
XElement option = permission.Elements("Option")
        .FirstOrDefault(op => op.Attribute("Name").Value == optionName);

// Add option if it doesn't exist
if (option == null)
    permission.Add(option = new XElement("Option", 
             new XAttribute("Name", optionName)));

option.Value = optionSetting.ToString();

I can't quite figure out what you are trying to accomplish, but the above will add a new Option to a Permission, and if the Permission doesn't exist, add it. 我不太清楚您要完成的工作,但是以上内容将为Permission添加一个新的Option,并且如果Permission不存在,请添加它。

I only ever use XElement (not XDocument) for the root node, so I changed it to be that (an XElement). 我只对根节点使用XElement(而不是XDocument),所以我将其更改为那个(XElement)。 The above code may work as is with using an XDocument. 上面的代码可能与使用XDocument一样工作。

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

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