2010-06-08 15 views
7

próbuję napisać danych XML za pomocą Stax gdzie sama treść jest HTMLJak napisać Niecytowany XML zewnątrz z CDATA

Gdy próbuję

xtw.writeStartElement("contents"); 
xtw.writeCharacters("<b>here</b>"); 
xtw.writeEndElement(); 

otrzymuję ten

<contents>&lt;b&gt;here&lt;/b&gt;</contents> 

Następnie zauważam metodę CDATA i zmieniam kod na:

xtw.writeStartElement("contents"); 
xtw.writeCData("<b>here</b>"); 
xtw.writeEndElement(); 

i tym razem wynik jest

<contents><![CDATA[<b>here</b>]]></contents> 

która nadal nie jest dobra. Co ja naprawdę chcę to

<contents><b>here</b></contents> 

Więc jest tam XML API/biblioteka, która pozwala mi pisać tekst surowe, nie będąc w sekcji CDATA? Do tej pory patrzyłem na Staxa i JDoma i nie wydają się tego oferować.

W końcu mógłbym użyć starego, dobrego StringBuildera, ale nie byłoby to eleganckie.

Aktualizacja:

Zgadzam się głównie z odpowiedziami tak daleko. Jednak zamiast <b>here</b> mógłbym mieć 1MB dokumentu HTML, który chcę osadzić w większym dokumencie XML. To, co sugerujesz, oznacza, że ​​muszę przeanalizować ten dokument HTML, aby zrozumieć jego strukturę. Chciałbym tego uniknąć, jeśli to możliwe.

Odpowiedź:

To nie jest możliwe, w przeciwnym razie można tworzyć nieważnych dokumentów XML.

+2

Gdyby było to możliwe, zbyt łatwo można zapisać nieprawidłowe pliki XML. Nie, że większość HTML w świecie rzeczywistym (to nie XHTML) to ** nie ** poprawny XML (zbyt wiele niezamkniętych tagów i atrybutów bez zmiany znaczenia). Wszystko to jest dobre dla HTML, ale niedozwolone dla XML, więc używanie CDATA jest naprawdę jedyną właściwą rzeczą do zrobienia, chyba że twój HTML jest faktycznie XHTML. –

+0

@ Joachim. Tak, w moim przypadku jest to XHTML. Właśnie dlatego wiem, że to jest poprawne i chcę je osadzić od razu bez żadnego przetwarzania. – kazanaki

Odpowiedz

3

Kwestia jest taka, że ​​nie jest tekst surowy jest to element tak powinno być pisanie

xtw.writeStartElement("contents"); 
xtw.writeStartElement("b"); 
xtw.writeCData("here"); 
xtw.writeEndElement(); 
xtw.writeEndElement(); 
+0

Myślę, że problem polega na tym, że on ma kropelkę, która MOŻE zawierać znaczniki. – ShiDoiSi

0

Problem nie jest "tutaj", to jest <b></b>.

Dodaj element <b> jako treść dziecka, a będziesz mógł to zrobić. Każda biblioteka taka jak JDOM lub DOM4J pozwoli ci to zrobić. Ogólny przypadek to przeanalizowanie zawartości w DOM XML i dodanie elementu głównego jako elementu potomnego o wartości <contents>.

Nie można dodawać wartości z uwzględnieniem zmiennoprzecinkowych poza sekcją CDATA.

0

Jeśli XML i HTML nie są zbyt duże, można zrobić obejście:

xtw.writeStartElement("contents"); 
xtw.writeCharacters("anUniqueIdentifierForReplace"); // <-- 
xtw.writeEndElement(); 

Kiedy masz XML jako ciąg znaków:

xmlAsString.replace("anUniqueIdentifierForReplace", yourHtmlAsString); 

co wiem, to nie jest tak ładne, ale to może działać.


Edycja: Oczywiście należy sprawdzić, czy yourHtmlAsString jest ważny.

+0

Bardzo sprytny! Dziękuję za ten pomysł. – kazanaki

+1

To jest naprawdę bardzo nieczysty hack. Jeśli nie chcesz, aby program piszący XML generował poprawny dokument XML, zamiast tego użyj łączenia z ciągami. – jarnbjo

+1

Jeśli wiesz, że masz prawidłowy kod XML, aby wprowadzić go jako obszar blob, działałoby to jednak, ale ryzykujesz, że wszystko jest dobrze uformowane. – Mark

0

Jeśli chcesz osadzić duży dokument HTML w dokumencie XML, to CDATA imho jest drogą do zrobienia. W ten sposób nie musisz rozumieć ani przetwarzać wewnętrznej struktury, a później możesz zmienić typ dokumentu z HTML na inny bez większych kłopotów. Również nie można osadzić, np. Instrukcje DOCTYPE bezpośrednio (tj. Jako dane strukturalne zachowujące semantykę instrukcji DOCTYPE). Muszą być przedstawiane jako postacie.

(Jest to przede wszystkim odpowiedź do aktualizacji, ale niestety nie mam wystarczająco dużo rep uwag ...............)

1

Jeśli chcesz do XML być zawarty jako XML, a nie jako dane znakowe, to musi zostać w pewnym momencie przeanalizowany. Jeśli nie chcesz samodzielnie wykonać parsowania, masz dwie możliwości:

(1) Użyj zewnętrznych analizowanych elementów - w takim przypadku zewnętrzny plik zostanie pobrany i przeanalizowany przez analizator składni XML. Gdy dane wyjściowe będą ponownie serializowane, będą zawierać zawartość zewnętrznego pliku.

[Patrz http://www.javacommerce.com/displaypage.jsp?name=entities.sql&id=18238]

(2) Zastosowanie XInclude - w tym wypadku plik musi być prowadzony thru procesor XInclude który połączy odniesienia XInclude do wyjścia. Większość procesorów xslt, a także xmllint również wykona xinclude z odpowiednią opcją.

[Zobacz: http://www.xml.com/pub/a/2002/07/31/xinclude.html]

(XSLT może być również używany do łączenia dokumentów bez użycia składni XInclude XInclude tylko zapewnia standardową składnię.)

0

nie widzę w czym jest problem z parsowania duży blok XML, który chcesz wstawić do swojego wyjścia. Użyj parsera StAX do przeanalizowania go i po prostu napisz kod, aby przekazać wszystkie zdarzenia do istniejącego serializera (zmienna "xtw").

0

Jeśli blob HTML jest rzeczywiście xhtml następnie sugeruję robić coś podobnego (w pseudo-kod):

xtw.writeStartElement("contents") 
XMLReader xtr=new XMLReader(); 
xtr.read(blob); 
Dom dom=xtr.getDom(); 
for(element e:dom){ 
    xtw.writeElement(e); 
} 
xtw.writeEndElement(); 

lub coś podobnego. Musiałem zrobić coś podobnego, ale użyłem innej biblioteki.