Вот версия LINQ.
Учитывая xml, как это:
var xml = @"
<inventory>
<hardware name=""PC"">
<software name=""Office""/>
<software name=""Safari""/>
<software name=""Windows""/>
</hardware>
<hardware name=""Mac"">
<software name=""Safari""/>
<software name=""Office""/>
<software name=""Leopard""/>
</hardware>
</inventory>";
Вот запрос, чтобы отделить его:
var xd = XDocument.Parse(xml);
var query =
from h in xd.Root.Elements()
from s in h.Elements()
select new
{
hardware = h.Attribute("name").Value,
software = s.Attribute("name").Value
};
var lookup = query.ToLookup(q => q.software, q => q.hardware);
И вот запрос, чтобы собрать его снова, перевернул по желанию:
var result =
new XDocument
(
new XElement
(
"inventory",
from s in query.Select(q => q.software).Distinct()
select new XElement
(
"software",
new XAttribute("name", s),
from h in lookup[s].Distinct()
select new XElement
(
"hardware",
new XAttribute("name", h)
)
)
)
);
/*
<inventory>
<software name="Office">
<hardware name="PC" />
<hardware name="Mac" />
</software>
<software name="Safari">
<hardware name="PC" />
<hardware name="Mac" />
</software>
<software name="Windows">
<hardware name="PC" />
</software>
<software name="Leopard">
<hardware name="Mac" />
</software>
</inventory>
*/