8.13. Tipo XML #

8.13.1. Creación de valores XML
8.13.2. Manejo de codificaciones
8.13.3. Acceso a valores XML

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 xmlvalue IS DOCUMENT se puede utilizar para evaluar si un valor xml 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.

8.13.1. Creación de valores XML #

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.

8.13.2. Manejo de codificaciones #

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.

Caution

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().

8.13.3. Acceso a valores XML #

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.