2014-04-14 2 views
0

XML 병합을 시도하고 있지만 매우 구체적인 요구 사항이 있습니다. 나는 이런 식으로 뭔가 만들기 위해이 두 파일을 병합 할두 개의 XML 파일을 스마트로 병합

<msg action="getcustomlists" class="lookup" ul="1"> 
    <host name="hp"/> 
</msg> 

<msg action="getcustomlists" class="newLookup" lac="statements"> 
    <environment type="lab"> 
    <login id="manual" /> 
    </environment> 
</msg> 

: 나는 두 개의 XML 파일을 다음 한

<msg action="getcustomlists" class="newLookup" lac="statements" ul="1"> 
    <host name="hp"/> 
    <environment type="lab"> 
    <login id="manual" /> 
    </environment> 
</msg> 

즉를, 나는 병합해야 속성 및 요소. 중복 된 속성으로 인해 충돌이 발생하는 경우 두 번째 파일로 결과를 재정의해야합니다.

DataSet.Merge (DataSet)를 시도했습니다. 그러나 그것은 내가 원하는 결과를주지 못하고있다. 도와주세요.

감사합니다, Harit

+0

XSLT를 사용해 보셨습니까? – Graymatter

+0

가능한 복제본은 http://stackoverflow.com/questions/6045010/how-can-i-merge-xml-files – Graymatter

+0

입니다. 레퍼런스로 나를 가리켜 주시겠습니까? –

답변

1

당신은 노드를 통해 반복하고 새로운 된 XmlDocument에 병합, 두 소스를 열고을 XmlDocument를 사용할 수 있습니다.

또한 XmlDocument를 사용하면 LINQ를 사용하여 충돌을 테스트 할 수 있으며이 작업을 단순화합니다.

XmlDocument MergeDocs(string SourceA, string SourceB) 
    { 

     XmlDocument docA = new XmlDocument(); 
     XmlDocument docB = new XmlDocument(); 
     XmlDocument merged = new XmlDocument(); 

     docA.LoadXml(SourceA); 
     docB.LoadXml(SourceB); 

     var childsFromA = docA.ChildNodes.Cast<XmlNode>(); 
     var childsFromB = docB.ChildNodes.Cast<XmlNode>(); 

     var uniquesFromA = childsFromA.Where(ch => childsFromB.Where(chb => chb.Name == ch.Name).Count() == 0); 
     var uniquesFromB = childsFromB.Where(ch => childsFromA.Where(chb => chb.Name == ch.Name).Count() == 0); 

     foreach (var unique in uniquesFromA) 
      merged.AppendChild(DeepCloneToDoc(unique, merged)); 

     foreach (var unique in uniquesFromA) 
      merged.AppendChild(DeepCloneToDoc(unique, merged)); 

     var Duplicates = from chA in childsFromA 
         from chB in childsFromB 
         where chA.Name == chB.Name 
         select new { A = chA, B = chB }; 

     foreach (var grp in Duplicates) 
      merged.AppendChild(MergeNodes(grp.A, grp.B, merged)); 

     return merged; 

    } 

    XmlNode MergeNodes(XmlNode A, XmlNode B, XmlDocument TargetDoc) 
    { 
     var merged = TargetDoc.CreateNode(A.NodeType, A.Name, A.NamespaceURI); 

     foreach (XmlAttribute attrib in A.Attributes) 
      merged.Attributes.Append(TargetDoc.CreateAttribute(attrib.Prefix, attrib.LocalName, attrib.NamespaceURI)); 

     var fromA = A.Attributes.Cast<XmlAttribute>(); 

     var fromB = B.Attributes.Cast<XmlAttribute>(); 

     var toAdd = fromB.Where(attr => fromA.Where(ata => ata.Name == attr.Name).Count() == 0); 

     foreach (var attrib in toAdd) 
      merged.Attributes.Append(TargetDoc.CreateAttribute(attrib.Prefix, attrib.LocalName, attrib.NamespaceURI)); 

     var childsFromA = A.ChildNodes.Cast<XmlNode>(); 
     var childsFromB = B.ChildNodes.Cast<XmlNode>(); 

     var uniquesFromA = childsFromA.Where(ch => childsFromB.Where(chb => chb.Name == ch.Name).Count() == 0); 
     var uniquesFromB = childsFromB.Where(ch => childsFromA.Where(chb => chb.Name == ch.Name).Count() == 0); 

     foreach (var unique in uniquesFromA) 
      merged.AppendChild(DeepCloneToDoc(unique, TargetDoc)); 

     foreach (var unique in uniquesFromA) 
      merged.AppendChild(DeepCloneToDoc(unique, TargetDoc)); 

     var Duplicates = from chA in childsFromA 
         from chB in childsFromB 
         where chA.Name == chB.Name 
         select new { A = chA, B = chB }; 

     foreach(var grp in Duplicates) 
      merged.AppendChild(MergeNodes(grp.A, grp.B, TargetDoc)); 

     return merged; 
    } 

    XmlNode DeepCloneToDoc(XmlNode NodeToClone, XmlDocument TargetDoc) 
    { 

     var newNode = TargetDoc.CreateNode(NodeToClone.NodeType, NodeToClone.Name, NodeToClone.NamespaceURI); 

     foreach (XmlAttribute attrib in NodeToClone.Attributes) 
      newNode.Attributes.Append(TargetDoc.CreateAttribute(attrib.Prefix, attrib.LocalName, attrib.NamespaceURI)); 

     foreach (XmlNode child in NodeToClone.ChildNodes) 
      newNode.AppendChild(DeepCloneToDoc(NodeToClone, TargetDoc)); 

     return newNode; 

    } 

나는 그것을 테스트하지 않았습니다 참고, 단지 메모리에서 수행하지만 이동하는 방법에 대한 아이디어를 얻을.

+1

당신을 하향 회선시키지 않았지만 나는 말할 것입니다. LINQ를 사용하려는 경우 XDocument가 훨씬 더 나은 선택입니다. 그렇지 않으면 정말로. – Magus

+0

참조 할 수있게 해주시겠습니까? –

+0

예를 들어 업데이트되었습니다. – Gusman

1

사용하여 LINQ - 투 - XML ​​+하여 XDocument

작성하지 확장 방법은 :

public static XDocument MergeXml(this XDocument xd1, XDocument xd2) 
{ 
    return new XDocument(
     new XElement(xd2.Root.Name, 
      xd2.Root.Attributes() 
       .Concat(xd1.Root.Attributes()) 
       .GroupBy (g => g.Name) 
       .Select (s => s.First()), 
      xd2.Root.Elements() 
       .Concat(xd1.Root.Elements()) 
       .GroupBy (g => g.Name) 
       .Select (s => s.First()))); 
} 

는이 기능을 사용하려면

var xd1 = XDocument.Load("test1.xml").MergeXml(XDocument.Load("test2.xml")); 

이 생산됩니다

<msg action="getcustomlists" class="newLookup" lac="statements" ul="1"> 
    <environment type="lab"> 
    <login id="manual" /> 
    </environment> 
    <host name="hp" /> 
</msg>