2009-11-09 7 views
0

나는 제어 할 수없는 다른 응용 프로그램에서 생성 된 두 개의 XML 파일을 가지고 있습니다. 첫 번째 파일은 설정 파일이며 두 번째 파일은 첫 번째 파일에 적용해야하는 변경 사항 목록입니다.XML 파일을 변경 목록과 병합

기본 설정 파일 : 여기

<?xml version="1.0"?> 
<preset> 
    <var id="9" opt="0" val="6666666"/> 
    <var id="9" opt="1" val="10000000"/> 
    <var id="9" opt="2" val="10000000"/> 
    <var id="9" opt="3" val="10000000"/> 
    <var id="9" opt="4" val="0"/> 
    <var id="10" opt="0" val="4"/> 
    <var id="11" opt="0" val="0"/> 
    <var id="15" opt="0" val="75"/> 
    <var id="22" opt="0" val="0,0,127,516" type="rect(l,t,r,b)"/> 
    <var id="23" opt="0" val="27,18,92,66" type="rect(l,t,r,b)"/> 
    <var id="24" opt="0" val="320"/> 
    ... Skip 300 lines ... 
</preset> 

그리고

변경 사항의 예는 다음과 같습니다

<?xml version="1.0"?> 
<preset> 
    <var id="15" opt="0" val="425"/> 
    <var id="22" opt="0" val="0,0,127,776" type="rect(l,t,r,b)"/> 
    <var id="26" opt="0" val="147"/> 
    <var id="27" opt="0" val="147"/> 
    <var id="109" opt="1" val="7"/> 
    <var id="126" opt="0" val="6,85,85,59" type="crv(t,m,b,vm)"/> 
    <var id="157" opt="0" val="1"/> 
    ... Skip 10 lines ... 
</preset> 

각 변수는 ID와 ID가 적용되는 최적화가 있습니다. 기본적으로, 나는 id="#"opt="#"이 같은 줄을 "변경"파일의 버전으로 바꾸려고합니다. 위의 예에서 id="15" opt="0"의 값은 75에서 425로 변경됩니다.

C#에서이 작업을 수행 할 때 명확한 방법이 있습니까? 처음에는 텍스트로 읽기와 바꾸기 유형을 사용하여 변경 사항을 단계별로 처리하는 것이 가장 깨끗한 것으로 보입니다. XmlDocument으로 처리하는 방법은 훨씬 더 많은 작업처럼 보입니다.

+0

이것은 일회성 일입니까, 아니면 정기적으로해야 할 일입니까? – Josh

+0

정기적으로. 기본적으로 사용자는 SDK가 자동으로 생성 한 변경 사항을 저장하고이를 원래 설정과 병합합니다. –

답변

3

이 파일이 매우 큰 얻는 경우에 대단히 비효율적이다, 그러나 이것은 당신이를 XMLDocuments 함께 할 수있는 방법입니다 :

XmlDocument main = new XmlDocument(); 
main.Load("main.xml"); 

XmlDocument changes = new XmlDocument(); 
changes.Load("changes.xml"); 

foreach (XmlNode mainNode in main.SelectNodes("preset/var")) 
{ 
    string mainId = mainNode.Attributes[ "id" ].Value; 
    string mainOpt = mainNode.Attributes[ "opt" ].Value; 

    foreach (XmlNode changeNode in changes.SelectNodes("preset/var")) 
    { 
     if (mainId == changeNode.Attributes[ "id" ].Value && 
      mainOpt == changeNode.Attributes[ "opt" ].Value) 
     { 
      mainNode.Attributes[ "val" ].Value = changeNode.Attributes[ "val" ].Value; 
     } 
    } 
} 

// save the updated main document 
main.Save("updated_main.xml"); 
+1

이것은 완벽하게 작동했습니다. 콘솔 응용 프로그램으로서 총 실행 시간은 584 줄의 XML 파일의 경우 21ms였으며 변경 사항이 20 개 였으므로 사용 방법에 매우 좋습니다. 감사! –

0

을 XmlDocument이 과정에 적합하고 다른 방법보다 훨씬 적은 작품입니다 것 너는 제안했다. XmlDocument와 같은 대용량 XML 파일을 사용하여 전체 문서를 메모리에로드하는 경우 다른 방법을 사용하여이 방법에 접근 할 수 있습니다. 해당하는 XmlDocument 객체로

  1. 로드 두 파일 :

    어쨌든을 XmlDocument 접근 방식은 같은 것을 할 것이다.

  2. 변경 파일 XmlDocument 개체의 var 노드 목록을 반복하고 원본 파일에서 xpath 쿼리를 실행합니다. 일치하는 ID가있는 노드를 검색하는 XmlDocument 개체 (원본 파일에서 SelectSingleNode() 메서드 사용) XmlDocument 객체) 발견되면 노드에서 편집해야하는 속성을 편집하십시오.
  3. 모든 수정 후 파일을 저장하십시오.

나는 당신에게 내가하는 일을 알고 있지만, 분명히 설명하지는 않을 것입니다. 나는 30 분 안에이 프로그램의 매우 거친 버전을 완성 할 수 있으며, C에서 약 1 년의 경험만을 가졌습니다.

2

효율성에 대해서는 잘 모르겠지만 Linq to XML에서는 간단합니다. 다음은 다소 거친 것이었지만 매우 멋진 LinqPAD가 프로그램을 실행할 수 있다는 것을 기억하고있었습니다. 작업을 수행하여 절

void Main() 
{ 
    XDocument settingsXML = XDocument.Load(@"c:\temp\settings.xml"); 
    XDocument updateXML = XDocument.Load(@"c:\temp\updates.xml"); 

    Console.WriteLine("Processing"); 

    // Loop through the updates 
    foreach(XElement update in updateXML.Element("preset").Elements("var")) 
    {  
     // Find the element to update  
     XElement settingsElement = 
      (from s in settingsXML.Element("preset").Elements("var") 
      where s.Attribute("id").Value == update.Attribute("id").Value && 
        s.Attribute("opt").Value == update.Attribute("opt").Value 
      select s).FirstOrDefault();  
     if (settingsElement != null)  
     {  
      settingsElement.Attribute("val").Value = update.Attribute("val").Value;  
      // Handling for additional attributes here 
     }  
     else  
     { 
      // not found handling  
      Console.WriteLine("Not found {0},{1}", update.Attribute("id").Value, 
                update.Attribute("opt").Value); 
     } 
    } 
    Console.WriteLine("Saving"); 
    settingsXML.Save(@"c:\temp\updatedSettings.xml"); 
    Console.WriteLine("Finis!"); 
} 

추가는 연습 문제로 남겨 :)

가 또 다른 예 here이다하지만 XML의 측면에서 더 많은 기능을 가지고 VB한다.

XElement와 값을 포함하는 동적 유형 목록을 생성하는 두 세트의 XML 데이터 조인을 사용하여 쿼리를 통해 진지하게 우아하게 처리 할 수도 있다고 생각합니다. 로 업데이트해야합니다.그러나 나는 이미 한밤중에 이것으로 이미 충분한 시간을 보냈다.

2

조인을 사용하여 Linq에서 XML을 사용하여 문서를 서로 연결하는 예제. 먼저 두 속성에서 일치하는 요소를 선택한 다음 해당 요소를 변경 파일의 새 값으로 업데이트합니다.

XDocument main = XDocument.Load("XMLFile1.xml"); 
XDocument changes = XDocument.Load("XMLFile2.xml"); 

var merge = from entry in main.Descendants("preset").Descendants("var") 
      join change in changes.Descendants("preset").Descendants("var") 
      on 
       new {a=entry.Attribute("id").Value, b=entry.Attribute("opt").Value} 
      equals 
       new {a=change.Attribute("id").Value, b=change.Attribute("opt").Value} 
      select new 
      { 
       Element = entry, 
       newValue = change.Attribute("val").Value      
      }; 

      merge.ToList().ForEach(i => i.Element.Attribute("val").Value = i.newValue); 

      main.Save("XMLFile3.xml"); 
+0

위의 Accepted Answer 루핑을 통해이 솔루션의 성능을 비교하는 방법에 대해 알고 싶습니다. –