El tipo de datos xml se puede utilizar para almacenar datos XML. Su
ventaja frente a almacenar datos XML en un campo text es que
comprueba la estructura correcta (well-formedness) de los valores de entrada, y existen
funciones de soporte para realizar operaciones con seguridad de tipos en él; consulta la Section 9.15. El uso de este tipo de datos requiere que la
instalación se haya compilado con configure --with-libxml.
El tipo xml puede almacenar “documentos” bien formados,
según lo definido por el estándar XML, así como fragmentos de “contenido”,
que se definen por referencia al más permisivo
“nodo documento”
del modelo de datos XQuery y XPath.
A grandes rasgos, esto significa que los fragmentos de contenido pueden tener
más de un elemento de nivel superior o nodo de caracteres. La expresión
se puede utilizar para evaluar si un valor xmlvalue IS DOCUMENTxml
particular es un documento completo o solo un fragmento de contenido.
Los límites y las notas de compatibilidad para el tipo de datos xml
se pueden encontrar en la Section D.3.
Para producir un valor de tipo xml a partir de datos de caracteres,
utiliza la función
xmlparse:
XMLPARSE ( { DOCUMENT | CONTENT } valor)
Ejemplos:
XMLPARSE (DOCUMENT '<?xml version="1.0"?><book><title>Manual</title><chapter>...</chapter></book>') XMLPARSE (CONTENT 'abc<foo>bar</foo><bar>foo</bar>')
Si bien esta es la única forma de convertir cadenas de caracteres en valores XML según el estándar SQL, también se pueden utilizar las sintaxis específicas de PostgreSQL:
xml '<foo>bar</foo>' '<foo>bar</foo>'::xml
también se pueden usar.
El tipo xml no valida los valores de entrada
contra una declaración de tipo de documento
(DTD),
incluso cuando el valor de entrada especifica una DTD.
Tampoco existe actualmente soporte integrado para validar contra
otros lenguajes de esquema XML como XML Schema.
La operación inversa, producir un valor de cadena de caracteres a partir de
xml, utiliza la función
xmlserialize:
XMLSERIALIZE ( { DOCUMENT | CONTENT } valor AS tipo [ [ NO ] INDENT ] )
tipo puede ser
character, character varying o
text (or un alias para uno de ellos). Nuevamente, según
el estándar SQL, esta es la única forma de realizar conversiones entre el tipo
xml y los tipos de caracteres, pero PostgreSQL también permite
simplemente realizar la conversión explícita (cast) del valor.
La opción INDENT hace que el resultado se imprima con sangría estética,
mientras que NO INDENT (que es el valor predeterminado)
simplemente emite la cadena de entrada original. La conversión a un tipo de caracteres
produce igualmente la cadena original.
Cuando un valor de cadena de caracteres se convierte hacia o desde el tipo
xml sin pasar por XMLPARSE o
XMLSERIALIZE, respectivamente, la elección de
DOCUMENT frente a CONTENT se
determina mediante el parámetro de configuración de sesión “XML option”
(opción XML), que se puede configurar utilizando el comando estándar:
SET XML OPTION { DOCUMENT | CONTENT };
o la sintaxis más al estilo de PostgreSQL:
SET xmloption TO { DOCUMENT | CONTENT };
El valor predeterminado es CONTENT, por lo que se permiten todas las formas de
datos XML.
Se debe tener cuidado al tratar con múltiples codificaciones de caracteres
en el cliente, el servidor y en los datos XML que se pasan a través de ellos.
Cuando se utiliza el modo de texto para pasar consultas al servidor y resultados de
consultas al cliente (que es el modo normal), PostgreSQL
convierte todos los datos de caracteres que se pasan entre el cliente y el
servidor y viceversa a la codificación de caracteres del extremo respectivo;
consulta la Section 23.3. Esto incluye representaciones en cadena
de valores XML, como en los ejemplos anteriores.
Esto normalmente significaría que las declaraciones de codificación contenidas en
los datos XML pueden quedar invalidadas a medida que los datos de caracteres se convierten
a otras codificaciones durante el trayecto entre el cliente y el servidor,
porque la declaración de codificación incrustada no se modifica. Para hacer frente
a este comportamiento, las declaraciones de codificación contenidas en las
cadenas de caracteres presentadas como entrada para el tipo xml
son ignoradas, y se asume que el contenido está en la
codificación actual del servidor. En consecuencia, para un procesamiento correcto,
las cadenas de caracteres de los datos XML deben enviarse desde el cliente en la
codificación actual del cliente. Es responsabilidad del cliente convertir los documentos
a la codificación actual del cliente antes de enviarlos al servidor, o ajustar la
codificación del cliente de manera adecuada. En la salida, los valores de tipo
xml no tendrán una declaración de codificación, y los clientes deben
asumir que todos los datos están en la codificación actual del cliente.
Cuando se utiliza el modo binario para pasar parámetros de consulta al servidor y resultados de consulta de vuelta al cliente, no se realiza ninguna conversión de codificación, por lo que la situación es diferente. En este caso, se observará una declaración de codificación en los datos XML y, si no está presente, se asumirá que los datos están en UTF-8 (según lo requerido por el estándar XML; ten en cuenta que PostgreSQL no admite UTF-16). En la salida, los datos tendrán una declaración de codificación que especifica la codificación del cliente, a menos que la codificación del cliente sea UTF-8, en cuyo caso se omitirá.
Sobra decir que el procesamiento de datos XML con PostgreSQL será menos propenso a errores y más eficiente si la codificación de los datos XML, la del cliente y la del servidor son las mismas. Dado que los datos XML se procesan internamente en UTF-8, los cálculos serán más eficientes si la codificación del servidor también es UTF-8.
Es posible que algunas funciones relacionadas con XML no funcionen en absoluto con datos que no sean ASCII
cuando la codificación del servidor no es UTF-8. Se sabe que esto es un problema en particular para
xmltable() y xpath().
El tipo de datos xml es inusual ya que no proporciona ningún
operador de comparación. Esto se debe a que no existe un algoritmo de comparación
bien definido y universalmente útil para datos XML. Una consecuencia de esto es
que no se pueden recuperar filas comparando una columna xml contra
un valor de búsqueda. Por lo tanto, los valores XML normalmente deberían ir
acompañados de un campo clave independiente, como un ID. Una solución alternativa
para comparar valores XML es convertirlos primero a cadenas de caracteres, pero ten en
cuenta que la comparación de cadenas de caracteres tiene poco que ver con un método
de comparación de XML útil.
Dado que no hay operadores de comparación para el tipo de datos xml,
no es posible crear un índice directamente en una columna de este tipo. Si se desean
búsquedas rápidas en datos XML, las soluciones alternativas posibles incluyen
convertir la expresión a un tipo de cadena de caracteres e indexar eso, o indexar
una expresión XPath. Por supuesto, la consulta real tendría que ajustarse para
buscar por la expresión indexada.
La funcionalidad de búsqueda de texto en PostgreSQL también se puede utilizar para acelerar las búsquedas de documentos completos de datos XML. El soporte de preprocesamiento necesario, sin embargo, aún no está disponible en la distribución de PostgreSQL.