2016-06-14 14 views
5

Używam kodu z Code Project, aby podzielić plik xml na wiele plików. To działa dobrze w tym poniższym przypadku: „Zgłoszenia” jest węzeł nadrzędny i kiedy podzielone jest między „Rejestracja”.net C# Spliting xml file

<Registrations> 
<Registration xmlns:i="..............."> 
    <RegistrationID>108260</RegistrationID> 
................... 
.................. 
</Registration> 
<Registration xmlns:i="..............."> 
    <RegistrationID>108260</RegistrationID> 
    ................... 
    .................. 
</Registration> 
<Registration xmlns:i="..............."> 
    <RegistrationID>108260</RegistrationID> 
    ................... 
    .................. 
</Registration> 

ale kod nie działa, gdy plik XML jest w tym formacie: " RegistrationOpenData”to węzeł główny, to istnieje inny węzeł«Zgłoszenia»i rozłam musi być wykonany między«Rejestracja»

<RegistrationOpenData xmlns:i="............" xmlns=""> 
<Description>......</Description> 
<InformationURL>..........</InformationURL> 
<SourceAgency>...............</SourceAgency> 
<SourceSystem>...........</SourceSystem> 
<StartDate>................</StartDate> 
<EndDate i:nil="true" /> 
<Registrations> 
<Registration xmlns:i="..............."> 
    <RegistrationID>108260</RegistrationID> 
................... 
.................. 
</Registration> 
<Registration xmlns:i="..............."> 
    <RegistrationID>108260</RegistrationID> 
................... 
.................. 
</Registration> 
<Registration xmlns:i="..............."> 
    <RegistrationID>108260</RegistrationID> 
................... 
.................. 
</Registration> 
</Registrations> 
</RegistrationOpenData> 

kod, który używam jest jak poniżej:

private void buttonSPLIT_Click(object sender, EventArgs e) 
{ 
    string sourceFile = @"D:\sample.xml"; 
    string rootElement = "RegistrationOpenData"; 
    string descElement = "Registration"; 
    int take = 1; 
    string destFilePrefix = "RegistrationsPart"; 
    string destPath = @"D:\PART\"; 

    SplitXmlFile(sourceFile, rootElement, descElement, take, 
     destFilePrefix, destPath); 

} 

private static void SplitXmlFile(string sourceFile 
        , string rootElement 
        , string descendantElement 
        , int takeElements 
        , string destFilePrefix 
        , string destPath) 
{   
    XElement xml = XElement.Load(sourceFile); 
    // Child elements from source file to split by. 
    var childNodes = xml.Descendants(descendantElement); 

    // This is the total number of elements to be sliced up into 
    // separate files. 
    int cnt = childNodes.Count(); 

    var skip = 0; 
    var take = takeElements; 
    var fileno = 0; 

    // Split elements into chunks and save to disk. 
    while (skip < cnt) 
    { 
     // Extract portion of the xml elements. 
     var c1 = childNodes.Skip(skip) 
         .Take(take); 

     // Setup number of elements to skip on next iteration. 
     skip += take; 
     // File sequence no for split file. 
     fileno += 1; 
     // Filename for split file. 
     var filename = String.Format(destFilePrefix + "_{0}.xml", fileno); 
     // Create a partial xml document. 
     XElement frag = new XElement(rootElement, c1); 
     // Save to disk. 
     frag.Save(destPath + filename); 
    } 
} 
+0

'XElement.Descendants' jest rekursywny w swoich wynikach. Myślę, że faktycznie mógłbyś szukać 'XElement.Elements' – pquest

+0

Próbowałem używać var ​​childNodes = xml.Elements (" Registration "); zamiast var childNodes = xml.Descendants (descendantElement); ale nadal nie działa. Nie daje wyników. – Karishma

+0

Czy możesz pokazać, jakie wyniki zamierzasz osiągnąć? –

Odpowiedz

1

Właśnie przetestowałem twój kod w VS 2015 i wygląda na to, że działa. Generuje 3 pliki XML o następującej treści:

<?xml version="1.0" encoding="utf-8"?> 
<RegistrationOpenData> 
    <Registration> 
    <RegistrationID>108260</RegistrationID> 
    </Registration> 
</RegistrationOpenData> 

Czy tego oczekujesz? Czy możesz podać więcej szczegółów na temat swojego problemu? Próbka

private static void SplitXmlFile(string sourceFile 
        , string rootElement 
        , string descendantElement 
        , int takeElements 
        , string destFilePrefix 
        , string destPath) 
{ 
    XElement xml = XElement.Load(sourceFile); 
    XNamespace ns = "http://services.hpd.gov"; // This line must be added. 
    xml = xml.Element(ns + rootElement); // rootElement must be "Registrations". And also this line must be added. 
    // Child elements from source file to split by. 
    var childNodes = xml.Descendants(ns + descendantElement); 
..... 
..... 

tu pracuje::

+0

Używam VS 2012. Pierwszy format, który określiłem w tym pytaniu, to oczekiwany wynik. Jeśli z pliku XML usunięty jest węzeł nadrzędny "RegistrationOpenData", kod działa poprawnie i plik jest dzielony. Ale jeśli oba "RegistrationOpenData" i "Registrations" są obecne, nic się nie dzieje. Bez błędów, bez podziału. – Karishma

0

jako szybkie rozwiązanie (zakładam, że nie chcesz, aby dokonać zmian w swoim skrypcie codeproject) można dodać tę linię https://dotnetfiddle.net/6sOOdH

+0

Próbowałem tej modyfikacji, ale nadal nie działa. Używam VS2012. Mam nadzieję, że tak nie jest. – Karishma

+0

W moim przypadku kod childNodes.Count() zwraca 0, a więc nie wprowadza nawet pętli while. – Karishma

+0

Witam, próbowałem go w skrzypcach i wchodzi do loop.https: //dotnetfiddle.net/6sOOdH –