2014-09-25 123 views
-2

让我把场景: 如果“学生”节点具有相同的子元素,然后合并“学生”节点。在这种情况下,如果在具有相同值的其他'学生'节点中找到'名称'节点,则需要将这2个'学生'节点与独特元素合并。在这种情况下,'名称'节点相同来了1次,'地址'节点来了2次。 同样输入XML可以有不同的子节点集合,每次可以有不同的名称。 下面是输入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); 
     } 
+0

如果您格式化xml,发布期望的xml,您尝试过的代码并询问您的具体问题,您可能会得到答案。 – 2014-09-25 16:51:50

回答

-3

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

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

'在那里进行分组。“你不觉得这是个问题吗? – 2014-09-25 17:19:40

+0

@ L.B不,我真的不认为这是个问题。这个问题似乎(我)是如何在XML中做到这一点,我的答案是不。将它转换为数据表,然后在那里做,这很容易。但我用一些可能有助于清理事情的链接更新了答案。 – 2014-09-25 19:29:38

+0

解析XML也有像* XmlDocument的*或*的XDocument *类更好的方法,你只能说*使用这个工具*,但问题是如何合并的节点,那么你如何使用您的工具来实现这一目标?下面 – 2014-09-25 19:41:36

相关问题