如果子节点的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);
        } 

如果子节点的xml相同,则合并父节点

这是一段糟糕的代码,我还没有时间清理它,但这很有效。

        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));