c# - Replace part of large XML file -
i have large xml file, , need replace elements name (and inner elements) element. example - if element e
:
<a> <b></b> <e> <b></b> <c></c> </e> </a>
after replace e
elem
:
<a> <b></b> <elem></elem> </a>
update: try use xdocument
xml size more 2gb , have systemoutofmemoryexception
update2: code, xml not transform
xmlreader reader = xmlreader.create("xml_file.xml"); xmlwriter wr = xmlwriter.create(console.out); while (reader.read()) { if (reader.nodetype == xmlnodetype.element && reader.name == "e") { wr.writeelementstring("elem", "val1"); reader.readsubtree(); } wr.writenode(reader, false); } wr.close();
update 3:
<a> <b></b> <e> <b></b> <c></c> </e> <i> <e> <b></b> <c></c> </e> </i> </a>
taking inspiration this blog post, can stream contents of xmlreader
straight xmlwriter
example code, handling node types. using writenode
, in example code, add node and child nodes, wouldn't able handle each descendant in source xml.
in addition, need make sure read end of element want skip - readsubtree
creates xmlreader
this, doesn't reading. need ensure read end.
the resulting code might this:
using (var reader = xmlreader.create(new stringreader(xml), rs)) using (var writer = xmlwriter.create(console.out, ws)) { while (reader.read()) { switch (reader.nodetype) { case xmlnodetype.element: var subtreereader = reader.readsubtree(); if (handleelement(reader, writer)) { readtoend(subtreereader); } else { writer.writestartelement(reader.prefix, reader.localname, reader.namespaceuri); writer.writeattributes(reader, true); if (reader.isemptyelement) { writer.writeendelement(); } } break; case xmlnodetype.text: writer.writestring(reader.value); break; case xmlnodetype.whitespace: case xmlnodetype.significantwhitespace: writer.writewhitespace(reader.value); break; case xmlnodetype.cdata: writer.writecdata(reader.value); break; case xmlnodetype.entityreference: writer.writeentityref(reader.name); break; case xmlnodetype.xmldeclaration: case xmlnodetype.processinginstruction: writer.writeprocessinginstruction(reader.name, reader.value); break; case xmlnodetype.documenttype: writer.writedoctype(reader.name, reader.getattribute("public"), reader.getattribute("system"), reader.value); break; case xmlnodetype.comment: writer.writecomment(reader.value); break; case xmlnodetype.endelement: writer.writefullendelement(); break; } } } private static void readtoend(xmlreader reader) { while (!reader.eof) { reader.read(); } }
obviously put whatever logic inside handleelement
, returning true
if element handled (and therefore ignored). implementation logic in example code be:
private static bool handleelement(xmlreader reader, xmlwriter writer) { if (reader.name == "e") { writer.writeelementstring("element", "val1"); return true; } return false; }
here working demo: https://dotnetfiddle.net/ffibu4
Comments
Post a Comment