Ho sempre trovato XML piuttosto complicato da elaborare. Non sto parlando di implementare un parser XML: sto parlando di usando un parser esistente basato sul flusso, come un parser SAX, che elabora il nodo XML per nodo.
Sì, è davvero facile imparare le varie API per questi parser, ma ogni volta che guardo il codice che elabora l'XML, trovo che sia un po 'contorto. Il problema essenziale sembra essere che un documento XML è logicamente separato in singoli nodi, eppure i dati tipi e gli attributi sono spesso separati dai dati reali, a volte da più livelli di nidificazione. Pertanto, quando si elabora individualmente un particolare nodo, è necessario mantenere un sacco di stato aggiuntivo per determinare dove siamo e cosa dobbiamo fare dopo.
Ad esempio, dato uno snippet da un tipico documento XML:
<book>
<title>Blah blah</title>
<author>Blah blah</author>
<price>15 USD</price>
</book>
... Come dovrei determinare quando ho incontrato un nodo di testo che contiene un titolo di un libro? Supponiamo di avere un semplice parser XML che agisce come un iteratore, dandoci il prossimo nodo nel documento XML ogni volta che chiamiamo XMLParser.getNextNode()
. Mi ritrovo inevitabilmente a scrivere codice come il seguente:
boolean insideBookNode = false;
boolean insideTitleNode = false;
while (!XMLParser.finished())
{
....
XMLNode n = XMLParser.getNextNode();
if (n.type() == XMLTextNode)
{
if (insideBookNode && insideTitleNode)
{
// We have a book title, so do something with it
}
}
else
{
if (n.type() == XMLStartTag)
{
if (n.name().equals("book")) insideBookNode = true
else if (n.name().equals("title")) insideTitleNode = true;
}
else if (n.type() == XMLEndTag)
{
if (n.name().equals("book")) insideBookNode = false;
else if (n.name().equals("title")) insideTitleNode = false;
}
}
}
In sostanza, l'elaborazione XML si trasforma rapidamente in un enorme ciclo guidato dallo stato, con molte variabili di stato utilizzate per indicare i nodi padre che abbiamo trovato in precedenza. In caso contrario, è necessario mantenere un oggetto stack per tenere traccia di tutti i tag nidificati. Questo diventa rapidamente soggetto a errori e difficile da mantenere.
Ancora una volta, il problema sembra essere che i dati a cui siamo interessati non sono direttamente associati a un singolo nodo. Certo, potrebbe essere, se scrivessimo l'XML come:
<book title="Blah blah" author="blah blah" price="15 USD" />
... ma raramente viene usato il XML nella realtà. Principalmente abbiamo nodi di testo come figli di nodi parent e abbiamo bisogno di tenere traccia dei nodi genitore per determinare a cosa si riferisce un nodo di testo.
Quindi ... sto facendo qualcosa di sbagliato? Esiste un modo migliore? A che punto l'utilizzo di un parser XML basato sul flusso diventa troppo macchinoso, per cui diventa necessario un parser DOM completo? Mi piacerebbe sapere da altri programmatori che tipo di idiomi usano durante l'elaborazione di XML con parser basati sul flusso. L'analisi XML basata sul flusso deve sempre trasformarsi in un'enorme macchina a stati?