c# - XElement with LINQ 在特定节点后添加节点

标签 c# xml linq xelement

我有这个 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

最佳答案

您当前代码的问题在于: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");

关于c# - XElement with LINQ 在特定节点后添加节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35702547/

相关文章:

c# - LINQ 数值分组

c# - 带有子检查器的 Unity 自定义检查器

java - XML 外部实体 (XXE) - 外部参数实体和外部通用实体漏洞

xml - XSLT 复制 - 从 1 个节点创建 2 个节点

c# - LINQ 到 XML : handling nodes that do not exist?

LINQ to DataSet,由多列区分

c# - 按搜索字符串过滤 CollectionViewSource - 绑定(bind)到 itemscontrol (WPF MVVM)

c# - 长时间解析不正确的 JSON 响应 ASP.NET MVC

c# - 如何以编程方式发布 SQL Server 数据库项目?

c - 使用 MiniXML 在 C 中解析 XML 文件