Autor wpisu: singles, dodany: 29.10.2011 18:39, tagi: php
Niedawno natrafiłem na problem polegający na konieczności wybrania z istniejącego pliku XML kilku losowych elementów. Tzn, dla przykładu – mamy plik z 50 pytaniami (nie wnikam w powody, dla których są one właśnie w XML, tylko uznaję to za pewnik), a przy każdym odświeżeniu strony do klienta ma trafiać zestaw kilku innych, losowo wylosowanych pytań. Nie jest to problem spotykany często, mam jednak nadzieję, że przedstawione tutaj rozwiązanie komuś się przyda.
Problem
Przypuśćmy, że mamy nastepujacy plik (mocno uproszczony przykład):
<?xml version="1.0" encoding="UTF-8"?> <questions> <question> <subject>Question 1</subject> <answer1>Answer 1</answer1> <answer2>Answer 2</answer2> <question> <!-- etc --> </questions>
Jak wspomniałem wcześniej, zależy nam każdorazowym wybraniu innego zestawu pytań i zwróceniu ich w postaci prawidłowo sformatowanego dokumentu XML.
Możliwe rozwiązania
Po przejrzeniu w sieci informacji na ten temat, najcześciej natrafiałem na podejście pt. „Zamień XMLa na arraya, wylosuj klucze, i z powrotem stwórz z tego XMLa.”
Niestety, w PHP (bez zastosowania dodatkowych bibliotek czy funkcji) nie jest to rzecz, którą da się załatwić w kilku linijkach. Dodatkowo, dochodzi tutaj kwestia dwukrotnej konwersji.
Podejście drugie polega na wykorzystaniu wyrażeń regularnych. Istnieje jednak dość powszczechna zasada, aby do parsowania HTMLa czy też XMLa nie używać wyrażeń regularnych, ponieważ nie mamy pewności czy dokument został sformatowany prawidłowo.
Możemy także wykorzystać XPath, wybierając po jednym elemencie o indeksie z zakresu (1 – liczba potenacjalnych elementów), pamiętając o tym, że elementy nie mogą się powtórzyć.
Jednakże, podejście drugie i trzecie ma to do siebie, że do wylosowanych elementów musimy dodać otaczającą ją resztę dokumentu, która nie zawsze może być tak uproszczona jak w naszym przykładze.
DOM na ratunek
A gdyby zamiast wybierania losowych elementów, które później zwracamy w postaci nowo utworzonego dokumentu XML, usuwać węzły z oryginalnego dokumentu? Wynikowo otrzymamy zestaw danych w tym samym formacie, bez konieczności dbania o resztę struktury dokumentu czy też parsowania.
W celu wykonania zadania, posłużyłem się klasą DOMDocument
(domyślnie dostępna w PHP), która udostępnia zestaw metod znanych z JavaScriptu jako części DOM API. Poniżej przedstawiam kawałek kodu wykorzystujący wspomniane przeze mnie podejście.