Я завжди вважав XML дещо громіздким для обробки. Я не кажу про реалізацію аналізатора XML: я говорю про використання існуючого аналізатора на основі потоку, як SAX-аналізатор, який обробляє вузол XML за вузлом.
Так, вивчити різні API для цих аналізаторів дуже просто, але коли я дивлюся на код, який обробляє XML, я завжди вважаю його дещо викривленим. Суттєвою проблемою, здається, є те, що XML-документ логічно розділений на окремі вузли, але типи даних та атрибути часто відокремлюються від фактичних даних, іноді на кількох рівнях вкладення. Тому, обробляючи будь-який конкретний вузол окремо, потрібно підтримувати багато зайвого стану, щоб визначити, де ми знаходимось і що нам робити далі.
Наприклад, наданий фрагмент з типового XML-документа:
<book>
<title>Blah blah</title>
<author>Blah blah</author>
<price>15 USD</price>
</book>
... Як я можу визначити, коли я стикався з текстовим вузлом, що містить назву книги? Припустимо, у нас є простий аналізатор XML, який діє як ітератор, даючи нам наступний вузол у документі XML кожного разу, коли ми дзвонимо XMLParser.getNextNode()
. Я неминуче знаходжу себе як такий код:
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;
}
}
}
В основному обробка XML швидко перетворюється на величезний цикл, керований станом, з великою кількістю змінних стану, які використовуються для позначення батьківських вузлів, які ми знайшли раніше. В іншому випадку об'єкт стека повинен підтримуватися для відстеження всіх вкладених тегів. Це швидко стає схильним до помилок і його важко підтримувати.
Знову ж таки, проблема здається в тому, що дані, які нас цікавлять, не пов'язані безпосередньо з окремим вузлом. Звичайно, це може бути, якби ми написали XML на зразок:
<book title="Blah blah" author="blah blah" price="15 USD" />
... але це рідко, як XML використовується в реальності. Здебільшого у нас текстові вузли є дітьми батьківських вузлів, і нам потрібно відстежувати батьківські вузли, щоб визначити, на що посилається текстовий вузол.
Отже ... чи я щось роблю не так? Чи є кращий спосіб? У який момент використання аналізатора на основі потоку XML стає занадто громіздким, тому необхідний повноцінний аналізатор DOM? Я хотів би почути від інших програмістів, які ідіоми вони використовують при обробці XML з потоковими аналізаторами. Потрібно завжди на основі потоку XML-розбору завжди перетворюватися на величезну машину?