Problem wygląda następująco:
Mam dokument xml, który chcę przekonwertować do hasha lub obiektu. Problem w xml jest taki, że czasami tag może wystąpić tylko raz a w innym przypadku kilka razy.
Przejrzałem kilka bibliotek i nie znalazłem dobrej biblioteki do parsowania/mapowania. A więc po kolei:
HTTParty - parser w tym gemie działa tak, że jeśli tag występuje raz to mapuje go na hash a jak występuje wielokrotnie to robi tablicę. Co prowadzi do nieścisłości, bo raz możemy otrzymać hash dla danego pola a raz tablicę
Happymapper - to jest mniej więcej to czego szukam, ale gem ten ma problemy z mapowaniem zagnieżdżonych elementów np.:
<a><b><a></a></b></a>
Po mapowaniu wyjdzie tak, że mamy dwa tagi a na pierwszym poziomie, co nie jest prawdą
Patrzyłem też na inne gem, ale większość używa nokogiri, a mam jakieś wrażenie, że nokogiri, działa dużo wolniej
W prostych parserach XML nie da się ustawić, że jakieś pole ma być zawsze tablicą), a te bardziej skomplikowane nie zawsze chcą działać prawidłowo.
Czego używanie do parsowania XML i jak radzicie sobie z sytuacją, gdy pole może występować wielokrotnie, a w dokumencie XML występuje tylko raz ?
używałem Nori. Ma pewne problemy, ale są do obejścia.
Co do zamiany kilku tagów na tablicę - tego nie przeskoczysz. Parser sam nie odgadnie że pojedynczy element powinien być tablicą, ew. możesz mu pomóc przez zadeklarowanie typu (<tag type="array"></tag> ).
W przypadku Nori możesz dopisać własną wersję parsera XML (domyślne są Nokogiri i REXML), wtedy na poziomie parsowania zanim tag trafi do Nori możesz mu dopisać potrzebne atrybuty. Ale to nie będzie eleganckie na dłuższą metę. Najbezpieczniej jest się z tym pogodzić i oprogramować przypadek że w hashu może wystąpić tablica.
Największy problem jaki napotkałem w Nori to parsowanie niektórych elementów jako string (edge case), tj. zamiast pełnego hasha możesz dostać wynik typu { :root => "<whole><xml><as><string/></as></xml></whole>"} (swoją drogą it’s a feature, not a bug).
Nori jest chyba najlepszym gemem, niestety nie podoba mi się, że ustawia masę zmiennych, i wygląda to okropnie.
Teraz skłaniam się nad prostym parsowaniem xml -> hash, a następnie przepuszczenie przez jakąś klasę/metodę transformującą. To rozwiązanie chyba jest najlepsze, gdyż węzły w tym xmlu nie do końca są udokumentowane (na tą chwilę jakaś dokumentacja zdawkowa jest, ale co jakiś czas pojawiają się nowe węzły)