如果子节点的xml相同,则合并父节点
本文关键字:合并 父节点 相同 子节点 xml 如果 | 更新日期: 2023-09-27 18:24:42
让我放一个场景:如果"学生"节点具有相同的子元素,则合并"学生"结点。在这种情况下,如果在其他具有相同值的"学生"节点中找到"名称"节点,则这2个"学生"结点需要与唯一元素合并。在这种情况下,相同的"Name"节点出现1次,而"Address"节点出现2次。此外,输入xml可以具有不同的子节点集,并且每次都可以具有不同名称。下面是输入xml
<Root>
<Student>
<Name>Tim</Name>
<Address>
<City>
<Location1>MEL</Location1>
</City>
</Address>
</Student>
<Student>
<Name>Tim</Name>
<Address>
<City>
<Location1>DEL</Location1>
</City>
</Address>
</Student>
<Student>
<Name>1</Name>
<FatherName>Papa</FatherName>
<Address>
<Suburb>1</Suburb>
<City>
<Location1>HNL</Location1>
</City>
</Address>
</Student>
<Student>
<Name>1</Name>
<MotherName>Mom</MotherName>
<Address>
<City>
<Location1>HNL</Location1>
</City>
</Address>
</Student>
</Root>
预期xml:
<Root>
<Student>
<Name>Tim</Name>
<Address>
<City>
<Location1>MEL</Location1>
</City>
</Address>
<Address>
<City>
<Location1>DEL</Location1>
</City>
</Address>
</Student>
<Student>
<Name>1</Name>
<FatherName>Papa</FatherName>
<Address>
<Suburb>1</Suburb>
<City>
<Location1>HNL</Location1>
</City>
</Address>
</Student>
<Student>
<Name>1</Name>
<MotherName>Mom</MotherName>
<Address>
<City>
<Location1>HNL</Location1>
</City>
</Address>
</Student>
</Root>
我尝试用下面的代码实现。我知道这不是很有效。
var newdoc = XDocument.Parse(input);
// 'restriction' is the concerned node
foreach (var element in newdoc.Descendants("restriction"))
{
if (skiptimes > 0)
{
skiptimes--;
continue;
}
//Get distinct node names for 'element'
var distinctNodeName = element.Elements().Select(cc => cc.Name).Distinct();
//delete if found 'freetext' node as the this do not need to be comapared
distinctNodeName = distinctNodeName.Where(n => n.LocalName.ToString() != "FreeText");
//Get distinct elements
var distinctElementName = element.Elements().Select(xx => xx).Distinct();
foreach (var nextelement in element.ElementsAfterSelf())
{
if (!nextelement.IsEmpty)
{
//Get distinct node names for 'nextelement'
var distinctNodeName2 = nextelement.Elements().Select(xx => xx.Name).Distinct();
//delete if found 'freetext' node as the this do not need to be comapared
distinctNodeName2 = distinctNodeName2.Where(n => n.LocalName.ToString() != "FreeText");
//Get distinct elements
var distinctElements2 = nextelement.Elements().Select(xx => xx).Distinct();
//From 'element' excluding the 'StopoverSegs' node which by default always come as last node
var subelements = element.Elements().Take(distinctNodeName.Count() - 1);
//From 'nextelement' excluding the 'StopoverSegs' node which by default always come as last node
var sub2 = nextelement.Elements().Take(distinctNodeName2.Count() - 1);
// Compare node name counts which are selected as distinct
if (distinctNodeName.Count() == distinctNodeName2.Count())
{
ArrayList fir = new ArrayList();
int arrcount = 0; ArrayList sec = new ArrayList();
//Add 'element' to array list for comparison
foreach (var firstSet in subelements)
{
fir.Add(firstSet.ToString()); arrcount++;
}
//Add 'nextelement' to array list for comparison
foreach (var secondSet in sub2)
{
sec.Add(secondSet.ToString());
}
//comparison . I could not get through to compare via SequenceEqual or other custom
//extension
for (int i = 0; i < arrcount; i++)
{
if (fir[i].ToString().Trim() != sec[i].ToString().Trim())
{
GotEqual = false;
break;
}
else
{
GotEqual = true;
}
}
if (GotEqual)
{
element.Add(nextelement.Elements().Except(element.Elements(), new ElementComparer()));
skiptimes++;
}
else
{
break;
}
}
}
}
finalXML.Add(element);
}
这是一段糟糕的代码,我还没有时间清理它,但这很有效。
var xDoc = XDocument.Parse("<and><restriction type='"Stopovers_Type'" Name='"STP'"><NbMaxOfStops>4</NbMaxOfStops><Charges1><FirstAmount Currency='"AUD'">10.00</FirstAmount></Charges1><StopoversSegs><GeoSpec><Location1>AKL</Location1><Location2>CHC</Location2></GeoSpec><ChargeIndicator>1</ChargeIndicator></StopoversSegs><StopoversSegs><GeoSpec><Location1>LAX</Location1><Location2>RAR</Location2></GeoSpec><ChargeIndicator>1</ChargeIndicator></StopoversSegs></restriction><restriction type='"Stopovers_Type'" Name='"STP'"><NbMaxOfStops>2</NbMaxOfStops><NbOfOutboundStops>1</NbOfOutboundStops><NbOfInboundStops>1</NbOfInboundStops><Charges1><FirstAmountNbOf>1</FirstAmountNbOf><FirstAmount Currency='"AUD'">301.00</FirstAmount><AdditionalAmountNbOf>1</AdditionalAmountNbOf><AdditionalAmount Currency='"AUD'">151.00</AdditionalAmount></Charges1><StopoversSegs><NbOfStops>1</NbOfStops><GeoSpec><Location1>LAX</Location1></GeoSpec><InboundOutboundIndicator>I</InboundOutboundIndicator><ChargeIndicator>1</ChargeIndicator></StopoversSegs></restriction><restriction type='"Stopovers_Type'" Name='"STP'"><NbMaxOfStops>2</NbMaxOfStops><NbOfOutboundStops>1</NbOfOutboundStops><NbOfInboundStops>1</NbOfInboundStops><Charges1><FirstAmountNbOf>1</FirstAmountNbOf><FirstAmount Currency='"AUD'">301.00</FirstAmount><AdditionalAmountNbOf>1</AdditionalAmountNbOf><AdditionalAmount Currency='"AUD'">151.00</AdditionalAmount></Charges1><StopoversSegs><NbOfStops>1</NbOfStops><GeoSpec><Location1>SFO</Location1></GeoSpec><InboundOutboundIndicator>O</InboundOutboundIndicator><ChargeIndicator>2</ChargeIndicator></StopoversSegs></restriction></and>");
var xDoc2 = XDocument.Parse("<and><restriction type='"Stopovers_Type'" Name='"STP'"><NbMaxOfStops>4</NbMaxOfStops><Charges1><FirstAmount Currency='"AUD'">10.00</FirstAmount></Charges1><StopoversSegs><GeoSpec><Location1>AKL</Location1><Location2>CHC</Location2></GeoSpec><ChargeIndicator>1</ChargeIndicator></StopoversSegs><StopoversSegs><GeoSpec><Location1>LAX</Location1><Location2>RAR</Location2></GeoSpec><ChargeIndicator>1</ChargeIndicator></StopoversSegs></restriction><restriction type='"Stopovers_Type'" Name='"STP'"><NbMaxOfStops>2</NbMaxOfStops><NbOfOutboundStops>1</NbOfOutboundStops><NbOfInboundStops>1</NbOfInboundStops><Charges1><FirstAmountNbOf>1</FirstAmountNbOf><FirstAmount Currency='"AUD'">301.00</FirstAmount><AdditionalAmountNbOf>1</AdditionalAmountNbOf><AdditionalAmount Currency='"AUD'">151.00</AdditionalAmount></Charges1><StopoversSegs><NbOfStops>1</NbOfStops><GeoSpec><Location1>LAX</Location1></GeoSpec><InboundOutboundIndicator>I</InboundOutboundIndicator><ChargeIndicator>1</ChargeIndicator></StopoversSegs></restriction><restriction type='"Stopovers_Type'" Name='"STP'"><NbMaxOfStops>2</NbMaxOfStops><NbOfOutboundStops>1</NbOfOutboundStops><NbOfInboundStops>1</NbOfInboundStops><Charges1><FirstAmountNbOf>1</FirstAmountNbOf><FirstAmount Currency='"AUD'">301.00</FirstAmount><AdditionalAmountNbOf>1</AdditionalAmountNbOf><AdditionalAmount Currency='"AUD'">151.00</AdditionalAmount></Charges1><StopoversSegs><NbOfStops>1</NbOfStops><GeoSpec><Location1>SFO</Location1></GeoSpec><InboundOutboundIndicator>O</InboundOutboundIndicator><ChargeIndicator>2</ChargeIndicator></StopoversSegs></restriction></and>");
xDoc.Root.Descendants().Where(w => w.Name == "StopoversSegs").Remove();
var lsDistinct = xDoc.Root.Elements().Select(s => s.ToString()).Distinct().ToList();
var lDistinct = lsDistinct.Select(s => Tuple.Create(s, XElement.Parse(s))).ToList();
var lStopNodes = xDoc2.Root.Elements().Select(s => Tuple.Create(XElement.Parse(s.ToString()), XElement.Parse(s.ToString()))).ToList();
foreach ( var stopNode in lStopNodes)
{
stopNode.Item1.Descendants("StopoversSegs").Remove();
}
var lStopNodesToDistinct = lStopNodes.Select(s => Tuple.Create(s.Item1.ToString(), s.Item2.Descendants("StopoversSegs"))).ToList();
foreach (var distinct in lDistinct)
{
distinct.Item2.Add(lStopNodesToDistinct.Where(w => w.Item1 == distinct.Item1).Select(s => s.Item2.Nodes()).ToArray());
var test = lStopNodesToDistinct.Where(w => w.Item1 == distinct.Item1).Select(s => s.Item2.Nodes()).ToArray();
}
xDoc.Root.Elements().Remove();
xDoc.Root.Add(lDistinct.Select(s => s.Item2));