2010-06-08 20 views
7

Estoy intentando escribir datos XML utilizando Stax en el que el contenido en sí es HTML¿Cómo escribo XML sin escape fuera de un CDATA

Si intento

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

consigo este

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

Luego noto el método CDATA y cambio mi código a:

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

y esta vez el resultado es

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

que todavía no es buena. Lo que realmente quiero es

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

Entonces, ¿hay una API XML/Biblioteca que me permite escribir texto sin formato sin estar en una sección CDATA? Hasta ahora he mirado a Stax y JDom y parece que no ofrecen esto.

Al final podría recurrir al viejo StringBuilder pero esto no sería elegante.

Actualización:

estoy de acuerdo con la mayoría de las respuestas hasta el momento. Sin embargo, en lugar de <b>here</b> podría tener un documento HTML de 1MB que quiero incrustar en un documento XML más grande. Lo que sugieres significa que tengo que analizar este documento HTML para comprender su estructura. Me gustaría evitar esto si es posible.

Respuesta:

No es posible, de lo contrario podría crear documentos XML no válidos.

+2

Si esto fuera posible, podría escribir demasiado fácilmente archivos XML no válidos. No es que la mayoría del HTML del mundo real (que no es XHTML) es ** no ** XML válido (demasiadas etiquetas sin cerrar y atributos sin escalar). Todo eso está bien para HTML, pero no para XML, por lo que usar CDATA es realmente lo único correcto, a menos que tu HTML sea realmente XHTML. –

+0

@Joachim. Sí, en mi caso es XHTML. Es por eso que sé que es válido y quiero incrustarlo de inmediato sin ningún procesamiento. – kazanaki

Respuesta

3

La cuestión es que no es texto sin formato es un elemento por lo que debería estar escribiendo

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

Creo que el problema es que tiene una mancha que PUEDE contener etiquetas. – ShiDoiSi

0

El problema no es "aquí", es <b></b>.

Agregue el elemento <b> como contenido de contenido y podrá hacerlo. Cualquier biblioteca como JDOM o DOM4J te permitirá hacer esto. El caso general es analizar el contenido en un XML DOM y agregar el elemento raíz como hijo de <contents>.

No puede agregar valores escapados fuera de una sección CDATA.

0

Si el XML y HTML no son demasiado grandes, se puede hacer una solución:

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

Cuando tienes tu XML como una cadena:

xmlAsString.replace("anUniqueIdentifierForReplace", yourHtmlAsString); 

lo sé, no es tan agradable, pero esto podría funcionar.


Editar: Por supuesto, debe comprobar si yourHtmlAsString es válido.

+0

¡Muy listo! Gracias por la idea. – kazanaki

+1

Esto es en realidad un truco muy sutil. Si no desea que el escritor XML produzca un documento XML válido, utilice la concatenación de cadenas para comenzar. – jarnbjo

+1

Si sabe que tiene XML válido para ingresar como blob, esto funcionaría, pero corre el riesgo de que todo esté bien formado. – Mark

0

Si desea incrustar un documento HTML grande en un documento XML, entonces CDATA imho es el camino a seguir. De esta forma, no tiene que comprender o procesar la estructura interna y luego puede cambiar el tipo de documento de HTML a otra cosa sin mucha molestia. También Creo que no puede incrustar, p. Instrucciones DOCTYPE directamente (es decir, como datos estructurados que conserva la semántica de la instrucción DOCTYPE). Deben ser representados como personajes.

(Esto es principalmente una respuesta a su actualización, pero por desgracia no tengo representante suficiente para comentar ...............)

1

Si desea que el XML para debe incluirse como XML y no como datos de caracteres, luego tiene que ser analizado en algún momento. Si no desea realizar manualmente el análisis, tiene dos alternativas:

(1) Usar entidades analizadas externas: en este caso, el analizador XML extraerá y analizará el archivo externo. Cuando la salida se vuelva a serializar, incluirá el contenido del archivo externo.

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

(2) Uso xinclude - en este caso, el archivo tiene que ser ejecutado a través de un procesador xinclude que fusionar las referencias XInclude en la salida. La mayoría de los procesadores xslt, así como xmllint, también incluirán x con una opción adecuada.

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

(XSLT también se puede utilizar para combinar documentos sin necesidad de utilizar la sintaxis XInclude XInclude simplemente proporciona una sintaxis estándar.)

0

no veo cuál es el problema con el análisis el bloque grande de XML que desea insertar en su salida. Utilice un analizador StAX para analizarlo, y simplemente escriba el código para reenviar todos los eventos a su serializador existente (variable "xtw").

0

Si la masa de html XHTML es en realidad te sugiero hacer algo así (en pseudo-código):

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

o algo por el estilo. Tuve que hacer algo similar una vez pero usé una biblioteca diferente.