我有两个XML文件,我想将这两个文件合并为一个。 但是怎么样?我已经尝试了很多,但没有任何帮助。 正如您所看到的,合并后的XML如果来自第一个XML,则会从第二个属性中删除该文本。 第二个元素必须由第一个属性的Id / Name / whatevername命令。 第三,如果XML 2中不存在节点,则必须在与XML 1中相同的位置创建节点。
这里显示的XML文件只是整个XML的一个片段,还有更多属性名称。
如何使用C#执行此操作?
XML 1
<APPLICATION>
<AC>
<CLASS Name="Hello1" Capt="do1"/>
<CLASS Name="Hello2" Capt="do2"/>
<CLASS Name="Hello5" Capt="do5"/>
<CLASS Name="Hello8" Capt="do8"/>
</AC>
<BO>
<ITEM Id="1" DefaultValue="name1"/>
<ITEM Id="3" DefaultValue="name3"/>
<ITEM Id="11" DefaultValue="name11"/>
<ITEM Id="12" DefaultValue="name12">
<VAL>
<REASON Id="Job1" SecondOne="Hallo"/>
</VAL>
</ITEM>
</BO>
<POP Id="Green" Value="Monster"/>
<POP Id="Blue" Value="Doggie"/>
XML 2
<APPLICATION>
<AC>
<CLASS Name="Hello1" Capt="dodo1"/>
<CLASS Name="Hello2" Capt="dodo2"/>
<CLASS Name="Hello3" Capt="dodo3"/>
<CLASS Name="Hello9" Capt="dodo9"/>
</AC>
<CARS Wheel="Fore" Default="45x255xZ"/>
<CARS Wheel="BACK" Default="45x255xZ"/>
<CARS Wheel="SPARE" Default="45x255xZ"/>
<BO>
<ITEM Id="1" DefaultValue="namename1"/>
<ITEM Id="3" DefaultValue=""/>
<ITEM Id="9" DefaultValue="name11"/>
<ITEM Id="10" DefaultValue="name12">
<VAL>
<REASON Id="Job1" SecondOne="Hallo"/>
</VAL>
</ITEM>
</BO>
合并后XML应如下所示:
<APPLICATION>
<AC>
<CLASS Name="Hello1" Capt="dodo1"/>
<CLASS Name="Hello2" Capt="dodo2"/>
<CLASS Name="Hello3" Capt="dodo3"/>
<CLASS Name="Hello5" Capt=""/>
<CLASS Name="Hello8" Capt=""/>
<CLASS Name="Hello9" Capt="dodo9"/>
</AC>
<CARS Wheel="Fore" Default="45x255xZ"/>
<CARS Wheel="BACK" Default="45x255xZ"/>
<CARS Wheel="SPARE" Default="45x255xZ"/>
<BO>
<ITEM Id="1" DefaultValue="namename1"/>
<ITEM Id="3" DefaultValue=""/>
<ITEM Id="9" DefaultValue="name11"/>
<ITEM Id="10" DefaultValue="name12">
<VAL>
<REASON Id="Job1" SecondOne="Hallo"/>
</VAL>
</ITEM>
<ITEM Id="11" DefaultValue=""/>
<ITEM Id="12" DefaultValue="">
<VAL>
<REASON Id="Job1" SecondOne=""/>
</VAL>
</ITEM>
</BO>
<POP Id="Green" Value=""/>
<POP Id="Blue" Value=""/>
Thanx的所有答案,但我仍然有一个问题,我不知道标记名是怎么回事,所以我不能硬编码标签。
我只需要举例说明它的样子。但是下次我获取XML文件时,上面的标签可能完全不同。这就是问题所在。所以我不能说新的XElement(“BO”,boChildren),因为下次这个标签不再存在了。
或者我不能硬编码==&gt; var cars = xDocuments.SelectMany(x =&gt; x.Root.Elements(“CARS”))。Merge();因为下次我得到我的XML文件“CARS”不再存在。
答案 0 :(得分:7)
我认为你可以用Linq to XML做到这一点。为每个段(AC,BO,CARS,POP)创建单独的查询,将它们连接在一起,然后将它们放在一个新文档中。
这是一个让你开始的小片段:
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace XML_Merge {
class Program {
static void Main(string[] args) {
// load two xdocs
var x1 = XDocument.Load("x1.xml");
var x2 = XDocument.Load("x2.xml");
// select the CLASS nodes from each
var c1 = x1.Descendants("AC").First().Descendants("CLASS");
var c2 = x2.Descendants("AC").First().Descendants("CLASS");
// this one gives the distinct union of the two, you can put that into the result xdoc.
var cComb =
c1
.Union(c2)
.Distinct(new ClassComparer()) // this uses the IEqualityComparer from below
.OrderBy(c => c.Attribute("Name").Value);
}
}
// This is required for Union to work. (Also Intersect etc)
class ClassComparer : IEqualityComparer<XElement> {
public bool Equals(XElement x, XElement y) { return x.Attribute("Name").Value == y.Attribute("Name").Value; }
public int GetHashCode(XElement obj) { return obj.Attribute("Name").Value.GetHashCode(); }
}
}
只需重复源文档中的其他节点,然后将它们全部放在一起。
祝你好运,格特 - 扬
答案 1 :(得分:3)
我建议你不要用C#做那件事。尝试尽可能使用XSLT,主要用于转换xmls。
如果你想使用C#,那么使用新的C#3.5 / 4 XDocument。它具有很好的基于LINQ的语法,使其更易于使用。
答案 2 :(得分:0)
您可以使用XmlDocument类。 检查此链接: http://support.microsoft.com/kb/311530
答案 3 :(得分:0)
你可以这样:
class APPLICATION
{
public APPLICATION()
{
this.Classes = new List<CLASS>();
this.Cars = new List<CARS>();
this.Items = new List<ITEM>();
this.Pops = new List<POP>();
}
public List<CLASS> Classes { get; set; }
public List<CARS> Cars { get; set; }
public List<ITEM> Items { get; set; }
public List<POP> Pops { get; set; }
public override string ToString()
{
string toString = string.Empty;
using (MemoryStream stream = new MemoryStream())
{
using (XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8))
{
writer.Formatting = Formatting.Indented;
writer.Indentation = 5;
writer.WriteStartDocument();
writer.WriteStartElement("APPLICATION");
writer.WriteStartElement("AC");
if (this.Classes != null && Classes.Count > 0)
{
foreach (CLASS c in Classes)
{
writer.WriteStartElement("CLASS");
writer.WriteAttributeString("Name", c.Name);
writer.WriteAttributeString("Capt", c.Capt);
writer.WriteEndElement(); //CLASS
}
}
writer.WriteEndElement(); //AC
if (this.Cars != null && Cars.Count > 0)
{
foreach (CARS c in Cars)
{
writer.WriteStartElement("CARS");
writer.WriteAttributeString("Wheel", c.Wheel);
writer.WriteAttributeString("Default", c.Default);
writer.WriteEndElement(); //CARS
}
}
writer.WriteStartElement("BO");
if (this.Items != null && Items.Count > 0)
{
foreach (ITEM c in Items)
{
writer.WriteStartElement("ITEM");
writer.WriteAttributeString("Id", c.Id);
writer.WriteAttributeString("DefaultValue", c.DefaultValue);
if (c.Reason != null)
{
writer.WriteStartElement("VAL");
writer.WriteStartElement("REASON");
writer.WriteAttributeString("Id", c.Reason.Id);
writer.WriteAttributeString("SecondOne", c.Reason.SecondOne);
writer.WriteEndElement(); //ITEM
writer.WriteEndElement(); //VAL
}
writer.WriteEndElement(); //ITEM
}
}
writer.WriteEndElement(); //BO
writer.WriteEndElement(); //APPLICATION
writer.WriteEndDocument();
writer.Flush();
stream.Position = 0;
XmlTextReader reader = new XmlTextReader(stream);
reader.MoveToContent();
toString = reader.ReadOuterXml();
writer.Close();
stream.Close();
}
}
return toString;
}
}
public class REASON
{
public REASON()
{
Id = string.Empty;
SecondOne = string.Empty;
}
public string Id { get; set; }
public string SecondOne { get; set; }
}
public class ITEM
{
public ITEM()
{
Id = string.Empty;
DefaultValue = string.Empty;
}
public string Id { get; set; }
public string DefaultValue { get; set; }
public REASON Reason { get; set; }
}
public class CARS
{
public CARS()
{
Wheel = string.Empty;
Default = string.Empty;
}
public string Wheel { get; set; }
public string Default { get; set; }
}
public class CLASS
{
public CLASS()
{
Name = string.Empty;
Capt = string.Empty;
}
public string Name { get; set; }
public string Capt { get; set; }
}
public class POP
{
public POP()
{
Id = string.Empty;
Value = string.Empty;
}
public string Id { get; set; }
public string Value { get; set; }
}
并像这样使用它:
APPLICATION application = new APPLICATION();
application.Classes = ... //Populate this with classes read from xml 1 and 2.
application.Cars = ... //Populate this with cars read from xml 1 and 2.
application.Items = ... //Populate this with items read from xml 1 and 2.
application.Pops = ... //Populate this with pops read from xml 1 and 2.
string yourXmlString = application.ToString();
答案 4 :(得分:0)
以下是一些可以帮助您入门的代码。但是,您有一些非常具体的要求如何从原始元素生成合并元素。您必须在扩展方法中实现它:
var xDocuments = new[] { XDocument.Parse(xml1), XDocument.Parse(xml2) };
var acChildren = xDocuments.SelectMany(x => x.Root.Elements("AC"))
.SelectMany(x => x.Elements()).Merge();
var cars = xDocuments.SelectMany(x => x.Root.Elements("CARS")).Merge();
var boChildren = xDocuments.SelectMany(x => x.Root.Elements("BO"))
.SelectMany(x => x.Elements()).Merge();
var pops = xDocuments.SelectMany(x => x.Root.Elements("POP")).Merge();
var mergedXDocument = new XDocument(
new XElement("APPLICATION",
new XElement("AC", acChildren),
cars,
new XElement("BO", boChildren),
pops
)
);
以下是扩展方法的模板:
public static class Extensions {
public static IEnumerable<XElement> Merge(this IEnumerable<XElement> xElements) {
// Implement the requirement:
// "the merged XML has left the text from the second attribute if it came from
// the first XML"
}
}