Если вы используете .NET 3.5, вы можете использовать семейство XDocument и расширения Linq для выполнения довольно легкой работы над задачей:
var doc1 = XDocument.Parse(stringContainingYourXML);
var groups = doc1.Root.Elements().ToLookup(elt => elt.Attribute("PageID").Value);
var unique = groups.AsEnumerable().Select(group => group.First());
var doc2 = new XDocument(new XElement("root", unique));
Объяснение этому заключается в том, что мы создаем таблицу поискав строке 2, где элементы, содержащие одинаковое значение для PageID
, сгруппированы вместе.Учитывая ваш пример XML, он берет 4 <Page/>
элементов и создает 3 группы, причем одна группа содержит оба элемента PageID="1"
.
В строке 3 мы перебираем 3 группы и извлекаем только первый элемент XMLдля одного, и в строке 4 мы помещаем эти 3 элемента в новый документ.В результате получается XML:
<root>
<Page PageID="**1**">
<Para ParaID="1" />
</Page>
<Page PageID="**2**">
<Para ParaID="**1**" />
</Page>
<Page PageID="**3**">
<Para ParaID="**1**" />
</Page>
</root>
Обновление: 2011/03/12
Приведенный ниже код учитывает требования к абзацам из дублированных экземпляров страницы, которые должны объединяться в автоматическом режиме.- способ улучшения.
Пересмотренное решение довольно ужасно по сравнению с предыдущим, но возиться со значениями ParaID (особенно в том формате, в котором они находятся) было довольно раздражающим.Я не горжусь этим, но вот оно:
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace SO {
class Program {
static void Main(string[] args) {
var doc1 = XDocument.Parse(xmlstr);
var groups = doc1.Root.Elements().ToLookup(page => page.Attribute("PageID").Value);
var doc2 = new XDocument(new XElement("root"));
foreach (var group in groups) {
var firstpage = group.First();
var startindex = firstpage.Elements("Para").Last().Attribute("ParaID").Value;
var lastindex = int.Parse(Regex.Match(startindex, @"\d+").Value);
// Duplicate pages...
firstpage.Add(
group.Skip(1)
.SelectMany(page => page.Elements("Para"))
.Select(
para => {
para.Attribute("ParaID").Value = Regex.Replace(
para.Attribute("ParaID").Value,
@"\d+",
m => (++lastindex).ToString()
);
return para;
}
)
);
doc2.Root.Add(firstpage);
}
Console.WriteLine(doc2);
Console.ReadKey(true);
}
}
}