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

时间:2013-11-16 03:33:29

标签: c# xml linq

大家好我一整天都在寻找使用LINQ将数据添加到现有XML文档的方法。我似乎能找到的就是如何创建新元素以及如何将它们添加到文件的末尾。我正在尝试创建一个应用程序,允许我添加FTP帐户并从Filezilla Ftp客户端更新现有的帐户,而无需手动执行此操作。这是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>

到目前为止,我已经能够弄清楚如何使用LINQ查询进入文档的正确位置,但不确定如何添加到它。任何帮助将不胜感激。下面是我用来帮助我找到正确位置的查询。

                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;

因此,在这种情况下,我需要做的是为特定用户添加另一个目录,该目录将在一致的基础上进行更改。许多情况都需要我创建一个全新的用户。提前感谢您的帮助。

好的,看完示例和给出的答案后,我想我已经开始接近了。但是,我仍然得到“父错过”异常或“对象引用”错误。以下是我用来尝试插入的代码。

            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();
        }

3 个答案:

答案 0 :(得分:2)

如果您尝试添加新的权限元素,可以使用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)。您的Linq必须更改以删除.Attribute(“Dir”)。值

如果您正在尝试和第二个“Dir”属性,则不能这样做。 XML属性应该是唯一的。

- 对评论的回应 -

“......我不是要创建另一个属性,而是另一个元素,它基本上会克隆它之前的那个,只是不同的目录路径等”

听起来好像要添加一个带有修改后的目录属性的额外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);

看看它是否能达到你想要的效果。

答案 1 :(得分:0)

系统地考虑一下。如何将xml元素添加到文档中的特定xml元素?

  1. 找到要添加到的xml元素。
  2. 获取/创建要添加的xml元素。
  3. 添加xml元素。
  4. 那么这份文件意味着什么?

    1. 找到您要添加的用户。如果找到:
    2. 创建新权限。
    3. 将新权限添加到用户的Permissions元素。
    4. 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;
      }
      

      我不确定你在做什么,但这应该会为你提供一个很好的起点。

答案 2 :(得分:0)

您可以在任何其他XElement之前,之后,之后添加XElement

根据您的查询添加/调整选项的演示:

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();

我无法弄清楚你想要完成什么,但上面会为Permission添加一个新选项,如果Permission不存在,请添加它。

我只对根节点使用XElement(不是XDocument),所以我把它改为(XElement)。上面的代码可以像使用XDocument一样工作。