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

时间:2023-01-04 01:05:53

Let me put the scenario: If the 'Student' node has same child elements then merge the 'Student' node. In this case if the 'Name' node is found in other 'Student' nodes with same value then those 2 'Student' nodes need to be merged with unique elements. In this case the 'Name' node being identical comes 1 time and the 'Address' node coming 2 times. Also the input xml can have different set of child nodes and can have different names every time. Below is Input xml

让我说一下这个场景:如果'Student'节点有相同的子元素,那么合并'Student'节点。在这种情况下,如果在具有相同值的其他“学生”节点中找到“名称”节点,那么这些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>

Expected xml:

预期的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>

I tried to implement with the below code. I know its not very efficient.

我尝试使用以下代码实现。我知道它效率不高。

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

1 个解决方案

#1


-3  

This is horrible code, and I haven't had time to clean it up, but this works.

这是一个可怕的代码,我没有时间清理它,但这是有效的。

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

#1


-3  

This is horrible code, and I haven't had time to clean it up, but this works.

这是一个可怕的代码,我没有时间清理它,但这是有效的。

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