【问题标题】:XElement with LINQ add node after specific node带有 LINQ 的 XElement 在特定节点之后添加节点
【发布时间】:2016-02-29 14:50:58
【问题描述】:

我有这个 XML:

<?xml version="1.0" encoding="utf-8"?>
<JMF SenderID="InkZone-Controller" Version="1.2">
  <Command ID="cmd.00695" Type="Resource">
    <ResourceCmdParams ResourceName="InkZoneProfile" JobID="K_41">
      <InkZoneProfile ID="r0013" Class="Parameter" Locked="false" Status="Available" PartIDKeys="SignatureName SheetName Side Separation" DescriptiveName="Schieberwerte von DI" ZoneWidth="32">
        <InkZoneProfile SignatureName="SIG1">
          <InkZoneProfile Locked="False" SheetName="S1">
            <InkZoneProfile Side="Front">
              <ColorPool Class="Parameter" DescriptiveName="Colors for the job" Status="Available">
                <InkZoneProfile Separation="PANTONE 647 C" ZoneSettingsX="0 0,003 " />
              </ColorPool>
            </InkZoneProfile>
          </InkZoneProfile>
        </InkZoneProfile>
      </InkZoneProfile>
    </ResourceCmdParams>
  </Command>
</JMF>

我正在尝试使用 XElement 和 Linq 在特定 node() 之后添加一个节点。但是我的 LINQ 查询总是返回 null。 试过这个:

            XElement InkZonePath = XmlDoc.Element("JMF").Elements("InkZoneProfile").Where(z => z.Element("InkZoneProfile").Attribute("Side").Value == "Front").SingleOrDefault();

还有这个:

            XmlDoc.Element("JMF")
                   .Elements("InkZoneProfile").Where(InkZoneProfile => InkZoneProfile.Attribute("Side")
                   .Value == "Front").FirstOrDefault().AddAfterSelf(new XElement("InkZoneProfile",
                   new XAttribute("Separation", x.colorname),
                   new XAttribute("ZoneSettingsX", x.colorvalues)));

我已经按照这些示例构建了这个查询:

Select XElement where child element has a value

Insert XElements after a specific node

LINQ-to-XML XElement query NULL

但它没有按预期工作。 LINQ 查询有什么问题?从我读过的内容来看,它应该可以工作(从逻辑上阅读我可以理解的表达方式)。

谢谢

EDIT-1:整个writexml方法

public void writexml(xmldatalist XMLList, variables GlobalVars)
        {

            XmlWriterSettings settings = new XmlWriterSettings
            {
                Indent = true,
                IndentChars = "\t",
                NewLineChars = Environment.NewLine,
                NewLineHandling = NewLineHandling.Replace,
                Encoding = new UTF8Encoding(false)
            };

            string DesktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            string FileExtension = ".xml";
            string PathString = Path.Combine(DesktopFolder, "XML");
            System.IO.Directory.CreateDirectory(PathString);


            foreach (List<xmldata> i in XMLList.XMLArrayList)
            {
                int m = 0;
                foreach (var x in i)
                {

                    string XMLFilename = System.IO.Path.GetFileNameWithoutExtension(x.xml_filename);                    
                    GlobalVars.FullPath = Path.Combine(PathString, XMLFilename + FileExtension);


                    if (!File.Exists(GlobalVars.FullPath))
                    {
                        XDocument doc = new XDocument(
                         new XDeclaration("1.0", "utf-8", "yes"),

                         new XElement("JMF",
                             new XAttribute("SenderID", "InkZone-Controller"),
                             new XAttribute("Version", "1.2"),
                        new XElement("Command",
                             new XAttribute("ID", "cmd.00695"),
                             new XAttribute("Type", "Resource"),
                        new XElement("ResourceCmdParams",
                            new XAttribute("ResourceName", "InkZoneProfile"),
                            new XAttribute("JobID", "K_41"),
                        new XElement("InkZoneProfile",
                            new XAttribute("ID", "r0013"),
                            new XAttribute("Class", "Parameter"),
                            new XAttribute("Locked", "False"),
                            new XAttribute("Status", "Available"),
                            new XAttribute("PartIDKeys", "SignatureName SheetName Side Separation"),
                            new XAttribute("DescriptiveName", "Schieberwerte von DI"),
                            new XAttribute("ZoneWidth", "32"),
                        new XElement("InkZoneProfile",
                            new XAttribute("SignatureName", "SIG1"),
                        new XElement("InkZoneProfile",
                            new XAttribute("Locked", "false"),
                            new XAttribute("SheetName", "S1"),
                        new XElement("InkZoneProfile",
                            new XAttribute("Side", "Front"),
                        new XElement("ColorPoolClass",
                            new XAttribute("Class", "Parameter"),
                            new XAttribute("DescriptiveName", "Colors for the job"),
                            new XAttribute("Status", "Available")
                            )))))))));
                        doc.Save(GlobalVars.FullPath);

                        XDocument XmlDoc = new XDocument();
                        XmlDoc = XDocument.Load(GlobalVars.FullPath);
                        XElement InkZonePath = XmlDoc.Root.Descendants("InkZoneProfile").Where(z => (string)z.Attribute("Side") == "Front").SingleOrDefault();

                        if (InkZonePath != null)
                        {
                            InkZonePath.AddAfterSelf(new XElement("InkZoneProfile",
                                   new XAttribute("Separation", x.colorname),
                                   new XAttribute("ZoneSettingsX", x.colorvalues)));

                        }
                        XmlDoc.Save(GlobalVars.FullPath);

                        }//Closing !FileExists
                    }//Closing inner foreach


            }//Closing outer foreach


        }//Closing writexml method

【问题讨论】:

标签: c# xml linq xelement


【解决方案1】:

您当前代码的问题出在:Element("JMF").Elements("InkZoneProfile") 由于InkZoneProfile 不是JMF 的直接子代,它不会返回任何内容。请改用Descendants

Check difference between Elements & Descendants.

这应该会给你正确的结果:-

 XElement InkZonePath = xdoc.Element("JMF").Descendants("InkZoneProfile")
                            .SingleOrDefault(z => (string)z.Attribute("Side") == "Front")

在此之后,您可以使用AddAfterSelf 添加您想要添加的任何节点。另请注意,我在这里使用了 SingleOrDefault,但是如果您有多个匹配节点,则可能会出现异常,在这种情况下,请考虑使用 FirstOrDefault

更新:

添加新节点:-

if (InkZonePath != null)
{
    InkZonePath.AddAfterSelf(new XElement("InkZoneProfile",
                             new XAttribute("Separation", "Test"),
                             new XAttribute("ZoneSettingsX", "Test2")));
}
//Save XDocument                              
xdoc.Save(@"C:\Foo.xml");

【讨论】:

  • 它成功了。谢谢。现在我只是在将这个新的 XElement 添加到 xdoc 时遇到了一些麻烦
  • @PabloCosta - 有什么问题?只需检查 InkZonePath 是否不为空。然后说:InkZonePath.AddAfterSelf(new XElement("InkZoneProfile",... 然后像这样保存 XmlDoc XmlDoc.Save(..Path);
  • InkZonePath 不为空(使用调试器检查)。然后我运行命令(InkZonePath.AddAfterSelf ......),没有任何反应。如果我添加一些 XmlDoc.Save ,它将仅显示最后一次循环迭代。我将发布一个新问题并将其链接到此处。
  • @PabloCosta - 我从来不知道你在一个循环中做这一切,看起来很乱。每次保存后请调试并检查XML文件。
  • 修复了我的朋友。我的错\我的错。在循环开始时,有一个命令删除文件(如果存在)。由于循环结束时总是有一个文件,我总是从头开始删除和创建它。现在最后一个问题,如果可以的话:我的 被添加到 之后 - 我需要在关闭标签之前添加它。我能做些什么来避免这种行为吗?我用正确的代码更新了帖子。
【解决方案2】:

您需要使用Descendants 方法而不是Elements

XElement InkZonePath = XmlDoc.Root.Descendants("InkZoneProfile").Where(z => (string)z.Attribute("Side") == "Front").SingleOrDefault();

if(InkZonePath !=null)
   InkZonePath.AddAfterSelf(new XElement("InkZoneProfile",
               new XAttribute("Separation", x.colorname),
               new XAttribute("ZoneSettingsX", x.colorvalues)));

【讨论】:

    【解决方案3】:

    您可以改用后代。

    var node  = XmlDoc.Descendants("InkZoneProfile").Where(x=> x.Attribute("Side") !=null && x.Attribute("Side").Value == "Front").FirstorDefault();
    

    【讨论】:

    • 这会引发异常。对象实例未设置为对象的实例。
    • @PabloCosta Linq 查询是正确的.....您的 XmlDoc 是什么类型?你能再检查一下吗?
    • @PabloCosta 是的找到了它....HasAttrbutes 属性使用不正确...尝试新代码
    • 成功了!谢谢。但是现在我如何添加这个节点?如果我把它留在那里,则不会添加数据。而且我不能使用 xmlDoc.Add(node)。
    • @PabloCosta Xelement 是引用类型,因此您对此 XElement 所做的任何更改都会反映在 XmlDoc 中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    相关资源
    最近更新 更多