现有两个结构一样,但部分节点内容不同的XML文件,需要根据一个XML的ID节点,覆盖另一个XML节点内容.
XML结构如下
<?xml version="1.0" encoding="gb2312"?>
<Xml>
<Data>
<ElementMatchModel id="3b226203-f535-4bdd-bedf-0e42503d613d" name="bxline_bxpoint_0">
<Link>3b226203-f535-4bdd-bedf-0e42503d613d.usx</Link>
<BuildingSource></BuildingSource>
<SphericalTransform>
<Location>118.0850858401120900,24.4822235205172980,-1.5400000000000000</Location>
</SphericalTransform>
<BBox>
<MinBoundary>0.0000000000000000,0.0000000000000000,0.0000000000000000</MinBoundary>
<MaxBoundary>0.0000000000000000,0.0000000000000000,0.0000000000000000</MaxBoundary>
</BBox>
<LonLatRect>0.0000000000000000,0.0000000000000000,0.0000000000000000,0.0000000000000000</LonLatRect>
</ElementMatchModel>
<ElementMatchModel id="427b5a0e-62e3-4c66-bf5a-5d435c60b96b" name="bxline_bxpoint_1">
<Link>427b5a0e-62e3-4c66-bf5a-5d435c60b96b.usx</Link>
<BuildingSource></BuildingSource>
<SphericalTransform>
<Location>118.0852246123423700,24.4819580362325690,-1.5600000000000001</Location>
</SphericalTransform>
<BBox>
<MinBoundary>0.0000000000000000,0.0000000000000000,0.0000000000000000</MinBoundary>
<MaxBoundary>0.0000000000000000,0.0000000000000000,0.0000000000000000</MaxBoundary>
</BBox>
<LonLatRect>0.0000000000000000,0.0000000000000000,0.0000000000000000,0.0000000000000000</LonLatRect>
</ElementMatchModel>
</Data>
</Xml>

上面是小程序的界面,分别选择两个文件
代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml.Linq;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class frmXml : Form
{
public frmXml()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.CheckFileExists = true;
fileDialog.CheckPathExists = true;
//判断用户是否正确的选择了文件
if (fileDialog.ShowDialog() == DialogResult.OK)
{
//获取用户选择的文件
FileInfo fileInfo = new FileInfo(fileDialog.FileName);
textBox1.Text = fileInfo.FullName;
}
}
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.CheckFileExists = true;
fileDialog.CheckPathExists = true;
//判断用户是否正确的选择了文件
if (fileDialog.ShowDialog() == DialogResult.OK)
{
//获取用户选择的文件
FileInfo fileInfo = new FileInfo(fileDialog.FileName);
textBox2.Text = fileInfo.FullName;
}
}
private void button3_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(textBox1.Text) || String.IsNullOrEmpty(textBox2.Text))
return;
XDocument xdocDest = XDocument.Load(textBox1.Text); //需要覆盖的文件
XDocument xdocSelc = XDocument.Load(textBox2.Text); //需要读取的文件
try
{
//查询并返回“id”,“location”的键值对
var dic = (from ElementMatchModel in xdocSelc.Element("Xml").Element("Data").Elements("ElementMatchModel")
select new
{
id = ElementMatchModel.Attribute("id").Value,
location = ElementMatchModel.Element("SphericalTransform").Element("Location").Value
}).ToDictionary(o => o.id, o => o.location);
foreach (KeyValuePair<string, string> pair in dic)
{
var selLocCollection = from test in xdocDest.Element("Xml").Element("Data").Elements("ElementMatchModel")
where test.Attribute("id").Value == pair.Key
select test;
//如果找到相同的ID,那么就更新"Location"元素的值
if (selLocCollection.ToArray<XElement>().Length > 0)
selLocCollection.Single<XElement>().Element("SphericalTransform").Element("Location").Value = pair.Value;
}
//覆盖匹配的元素值后,生成一个新文件并保存
xdocDest.Save(System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) + "\\" + "test.xml");
MessageBox.Show("ok");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
上面是把需要更新的部分返回一个Dictionary,再在循环中查找并更新,原本我想用联合查询更新的,但貌似行不通,非得分几步完成,如有linq高手会用更简洁的代码写出来,不吝赐教!