【问题标题】:How to add Parent node if Child node elements are equal?如果子节点元素相等,如何添加父节点?
【发布时间】:2017-11-02 10:32:10
【问题描述】:

我有大量的 xml 数据。因此,"SECTION" 包含 "Piece" 节点,它们对于 "SECTION name="RF1WB-1"SECTION name="RF1WB-2"SECTION name="RF1WB-3" 具有相同的值。因此,如果 "Piece" 标记包含与第二个 XML 中所示相同的值,我想将 "Parent" 添加为它们的父节点。

如果子节点元素包含相同的值,如何添加父节点?

XmlDocument doc = new XmlDocument();
doc.Load("..\\MFAB1.xml");        
XmlNodeList xnList = doc.SelectNodes("MFAB.ini/SECTION");
foreach (XmlNode xn in xnList)
{
    if (xn.HasChildNodes)
    {
        foreach (XmlNode item in xn.SelectNodes("Piece"))
        {
            if (xn.ChildNodes[0].InnerText.ToString().Contains(s3))
            {
                d1.Piece = xn.ChildNodes[0].InnerText.ToString();
            }
            ______________
            ______________
            ______________
        }
    }
}

输入文件:

<?xml version="1.0" encoding="UTF-8"?>
<MFAB.ini>
 <SECTION name="RF1WB-1">
    <Piece>
      RF1-1
    </Piece>
</SECTION>
  <SECTION name="RF1WB-2">
    <Piece>
      RF1-1
    </Piece>
</SECTION>
  <SECTION name="RF1WB-3">
    <Piece>
      RF1-1
    </Piece>
  </SECTION>
  <SECTION name="RF1-2WB-1">
    <Piece>
      RF1-2
    </Piece>
 </SECTION>
  <SECTION name="RF1-2WB-2">
    <Piece>
      RF1-2
    </Piece>
 </SECTION>
</MFAB.ini>

预期的输出文件:

我需要的是:

<?xml version="1.0" encoding="UTF-8"?>
<MFAB.ini>
<Parent name = "RF1-1">
 <SECTION name="RF1-1WB-1">
    <Piece>
      RF1-1
    </Piece>
</SECTION>
  <SECTION name="RF1-1WB-2">
    <Piece>
      RF1-1
    </Piece>
</SECTION>
  <SECTION name="RF1-1WB-3">
    <Piece>
      RF1-1
    </Piece>
  </SECTION>
</Parent>
<Parent name = "RF1-2">
  <SECTION name="RF1-2WB-1">
    <Piece>
      RF1-2
    </Piece>
 </SECTION>
  <SECTION name="RF1-2WB-2">
    <Piece>
      RF1-2
    </Piece>
 </SECTION>
</Parent>
</MFAB.ini>

【问题讨论】:

  • 所以您希望根据自己的算法对数据进行分组?
  • 是的。也尝试了 LINQ,但没有运气。根据“Piece”节点元素需要将父元素添加到其中。是的,为他们定义了类。我也得到了所有的数据和元素。只需为其添加“父”标签。谢谢。
  • 你把它们分组?你有任何定义你的 xml 的类吗?
  • 是的,我现在更新了。

标签: c# .net xml linq linq-to-xml


【解决方案1】:

您可以通过&lt;Piece&gt;标签对元素进行分组,然后将它们作为&lt;Parent&gt;标签的子元素:

var xml = XDocument.Load(@"input file");

var result = new XElement(xml.Root.Name, xml.Root.Attributes().ToArray(),
    xml.Root.Elements().GroupBy(x => x.Element("Piece").Value.Trim()).Select(x =>
        new XElement("Parent", new XAttribute("name", x.Key), x))
    );

result.Save(@"output file");

【讨论】:

  • 在“x.Element("Piece").Value.Trim())”处抛出空引用异常
  • 使用您的输入文件进行了精确测试并且工作正常。如果它抛出空引用异常,这意味着您正在测试的文件与您与我们共享的文件不同,例如有一个元素没有Piece 标签或标签的值为空。
  • @MadhuKumar 我猜只需添加x.Element("Piece")?.Value?.trim() 就足够了;)
  • @Icepickle 从技术上讲已经足够了,但这意味着文件有一些问题,不能按Piece分组。
  • 是的,或者这意味着他的规范不够具体 :) 无论如何,这将允许他作为额外的父级处理空值 :) 当然它仍然可以分组,只是父级的 name 属性将为 null
【解决方案2】:

为了方便您自己,您可以使用XmlSerializer 来读取您的数据,并且您可以像这样为您的 Xml 定义一个 dto

[XmlRoot("MFAB.ini")]
public class Mfab {
    [XmlElement("SECTION")]
    public Section[] Sections { get; set; }
}

public class Section {
    [XmlAttribute("name")]
    public string Name { get; set; }
    [XmlElement("Piece")]
    [XmlText]
    public string Piece { get; set; }
}

这将按原样读取您的文档,将您的所有部分作为 Mfab 类的一部分(抱歉,我不知道这些类的更好名称;))

这个 Xml,你可以这样阅读

private static T GetXmlFromFile<T>(string filename) {
    XmlSerializer xs = new XmlSerializer(typeof(T));
    using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        return (T)xs.Deserialize(fs);
    }
}

这会给你一个包含所有部分的类。现在,既然你想重新格式化你的数据,你应该创建一个新的类来保存父部分,然后创建一个新的 xml 根来保存它们

[XmlRoot("MFAB.ini")]
public class MfabWithParents {
    [XmlElement("PARENT")]
    public ParentSection[] Parents { get; set; }
}

public class ParentSection {
    [XmlAttribute("name")]
    public string Name { get; set; }
    [XmlElement("SECTION")]
    public Section[] Sections { get; set; }
}

ParentSection 仍然重用之前创建的 Section 类。

现在要进行转换,我们可以执行以下步骤

// get the xml from a file
var source = GetXmlFromFile<Mfab>(Path.Combine(Environment.CurrentDirectory, "data.xml"));
// group all the sections by it's Piece
var groupedSections = source.Sections.GroupBy(section => section.Piece);
// convert the sections from the Grouped section to a parent section with name as attribute
var parentSections = groupedSections.Select(grp => new ParentSection
{
    Name = grp.Key,
    Sections = grp.ToArray()
}).ToArray();
// save the xml to a new file (which could now be read with the MfabWithParents class)
SaveToXml(new MfabWithParents { Parents = parentSections }, Path.Combine(Environment.CurrentDirectory, "data2.xml"));

然后保存方法如下所示

private static void SaveToXml(object data, string filename) {
    XmlSerializer xs = new XmlSerializer(data.GetType());
    using (var fs = new FileStream(filename, FileMode.Create, FileAccess.Write)) {
        xs.Serialize(fs, data);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-25
    • 2021-12-28
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    • 1970-01-01
    相关资源
    最近更新 更多