如果子节点元素相等,如何添加父节点?
How to add Parent node if Child node elements are equal?
我有非常大的 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>
您可以按 <Piece>
标签对元素进行分组,然后以这种方式将它们作为 <Parent>
标签的子标签:
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");
为了让您自己更轻松,您可以使用 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 class 的一部分(抱歉,我不知道 classes 的更好名称;))
这个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);
}
}
这将为您提供一个包含所有部分的 class。现在,既然你想重新格式化你的数据,你应该创建一个新的 class 来保存父部分,然后创建一个新的 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
class
现在要做改造,我们可以执行以下步骤
// 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);
}
}
我有非常大的 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>
您可以按 <Piece>
标签对元素进行分组,然后以这种方式将它们作为 <Parent>
标签的子标签:
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");
为了让您自己更轻松,您可以使用 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 class 的一部分(抱歉,我不知道 classes 的更好名称;))
这个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);
}
}
这将为您提供一个包含所有部分的 class。现在,既然你想重新格式化你的数据,你应该创建一个新的 class 来保存父部分,然后创建一个新的 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
class
现在要做改造,我们可以执行以下步骤
// 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);
}
}