XmlReader - jak ładnie(poprawnie) parsować duzego XML-a

0

cześć
jest duzy XML -trzeba go przeprasować, w XmlReaderze we wszystkich przykładach jakoś ostrasza mnie ifologia
np:

if((xmlReader.NodeType == XmlNodeType.Element) && (xmlReader.Name == "Cube"))
{
   if(xmlReader.HasAttributes)
           Console.WriteLine(xmlReader.GetAttribute("currency") + ": " + xmlReader.GetAttribute("rate"));                    
}

przez ładne rozumiem utrzymywalne, testowalne, ladnie napisane, z małą liczbą ifów

co sądzicie o czymś takim - slownik nazwa węzła do Parsera (lub Funkcji parsującej)

var dict = new Dictionary<string, IElementParser> ();

if(xmlReader.NodeType == XmlNodeType.Element)
{
  if( dict.TryGetValue(xmlReader.Name, var out parser))
 {
   parser.Parse(xmlReader);
 }
}

Myślę tez aby wykorzystać DI kontener coś na zasadzie Command Handlerów dla typów, gdzie typem byłby parser danego elementu

class AddressParser : IElementParser<Address>
{
    T Parse(XmlReader xmlReader){ return T}
}
//potem rejestorwać automatycznie tego typu klasy w DI kontenerze 

//parser - reslove obiektu i parsowanie
if(xmlReader.NodeType == XmlNodeType.Element)
{
//get enum from string -> z xmlReader.Name na enum
var parser = scope.ServiceProvider.GetRequiredService(IElementParser<enumValue>);
parser.Parse(xmlRader);
}

Co myślicie o tych pomysłach?
Macie z tym jakieś doświadczenie?
z góry dziękuję za sugestie i odpowiedzi

1

W pierwszej kolejności zazwyczaj deserializuje to do obiektów w c# wtedy zazwyczaj łatwiej jest się posługiwać takimi obiektami i dopiero wtedy robić z tym co chce.

0

A ty nie chcesz go po prostu zdeserializować do obiektu tak jak wspomniał @Kardash ?

0

@some_ONE: @Kardash
dzięki za odpoweidź

Deserializacja jest spoczko - ale mam jedno pytanie
Czy deserializacja działa strumieniowo (XmlReader) czy jest to ładowanie pliku xml do pamięci?

Z tego co rozumiem to
to takie podejście pozwala traktować plik jak strumień i czytac kolejne porcje danych

XmlReader reader = XmlReader.Create("file.xml", settings);
reader.MoveToContent();

while (reader.Read()) {}

Plik XML jest duży (kilkaset MB, albo i więcej nawet) - dlatego też optymalizacja zuzycia zasobów tez by się przydala

taki przykład

class Program
    {
        static void Main(string[] args)
        {
            List<MyObject> myObjects = new List<MyObject>();
            XmlSerializer serializer = new XmlSerializer(typeof(List<MyObject>));
            XmlReader reader = XmlReader.Create("objects.xml");
            myObjects = (List<MyObject>)serializer.Deserialize(reader);

            // now you can perform operations on your list of MyObject objects,
            // no manual XML parsing necessary.

            Console.WriteLine("Press <ENTER> key to exit.");
            Console.ReadLine();
        }
    }

jeśłi dobrze rozumiem to wg instrukcji
https://docs.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlserializer.deserialize?view=netcore-3.1#System_Xml_Serialization_XmlSerializer_Deserialize_System_IO_Stream_

może być to przetwarzane strumieniowo?

0

Witam,

A wiesz dokładnie co masz w tym XML-u? Jeśli jest to stała struktura i bardzo dużo rekordów to osobiście powiązałbym odczyt sekwencyjny z deserializacją pojedyńczego obiektu. Może brzmi przekombinowanie ale możesz z całości zrobić coś na wzór PIPE(odczytuje blok tekstu pomiędzy 2 tagami, robię z tego XML-a i deserializuje). Wszystko opiera się na 'yield return'.

Pozdrawiam,

mr-owl

1 użytkowników online, w tym zalogowanych: 0, gości: 1