Capítulo 14: XML

XML para pruebas

Éste es el pequeño documento XML que utilizaremos durante las pruebas de este capítulo:

<?xml version="1.0"?>
<reparto>
  <papel>
    <personaje protagonista="si">Rick Deckard</personaje>
    <interprete>Harrison Ford</interprete>
  </papel>
  <papel>
    <personaje protagonista="no">Roy Batty</personaje>
    <interprete>Rutger Hauer</interprete>
  </papel>
  <papel>
    <personaje protagonista="no">Rachael</personaje>
    <interprete>Sean Young</interprete>
  </papel>
</reparto>

Datos de trabajo

Ejecuta la siguiente consulta para modificar la tabla de películas:

USE videoteca;

ALTER TABLE
  pelicula
ADD
  reparto TEXT NOT NULL;

Ahora, actualiza la tabla de películas:

USE videoteca;

UPDATE
  pelicula
SET
  reparto =
   '<reparto>
      <papel protagonista="si">
        <personaje>Rick Deckard</personaje>
        <interprete>Harrisond Ford</interprete>
      </papel>
      <papel protagonista="no">
        <personaje>Roy Batty</personaje>
        <interprete>Rutger Hauer</interprete>
      </papel>
      <papel protagonista="no">
        <personaje>Rachael</personaje>
        <interprete>Sean Young</interprete>
      </papel>
    </reparto>'
WHERE
  id = 1;

ExtractValue

Directamente sobre una cadena de texto:

SELECT ExtractValue(
 '<papel>
    <personaje>Roy Batty</personaje>
    <interprete>Rutger Hauer</interprete>
  </papel>',
  '/papel/personaje'
) AS personaje;

Sobre los datos de una tabla:

USE videoteca;

SELECT
  ExtractValue(
    reparto,
    '/reparto/papel/personaje'
  ) AS personajes
FROM
  pelicula
WHERE
  id = 1;

SELECT
  ExtractValue(
    reparto,
    '/reparto/papel/@protagonista'
  ) AS personajes
FROM
  pelicula
WHERE
  id = 1;

Un procedimiento almacenado para que la lista de personajes aparezca separada por comas:

DELIMITER //

DROP PROCEDURE IF EXISTS pa_personajes_obtener;
CREATE PROCEDURE pa_personajes_obtener (
  idpelicula INT
)
BEGIN

DECLARE i INT DEFAULT 1;
DECLARE j INT DEFAULT 0;

DECLARE personajes TEXT DEFAULT '';
DECLARE personaje TEXT DEFAULT '';

SELECT
  ExtractValue(reparto, 'count(/reparto/papel)')
INTO
  j
FROM
  pelicula
WHERE
  id = idpelicula;

WHILE i <= j DO

  SELECT
    ExtractValue(
      reparto,
      '/reparto/papel[$i]/personaje')
  INTO
    personaje
  FROM
    pelicula
  WHERE
    id = idpelicula;

  SELECT
    IF(
      i <> j,
      CONCAT(personaje, ', '),
      personaje)
  INTO personaje;

  SET personajes = CONCAT(personajes, personaje);

  SET i = i + 1;

  END WHILE;

  SELECT personajes;

END //

DELIMITER ;

Para utilizarlo:

USE videoteca;

CALL pa_personajes_obtener(1);

UpdateXML

Modificación de valores dentro de un fragmento XML:

USE videoteca;

UPDATE
  pelicula
SET
  reparto = UpdateXML(
    reparto,
    '/reparto/papel[1]/interprete',
    '<interprete>Harrison Ford</interprete>'
  )
WHERE
  id = 1;

¿Ha tenido éxito el cambio?

USE videoteca;

SELECT
  ExtractValue(
    reparto,
    '/reparto/papel[1]/interprete'
  ) AS interprete
FROM
  pelicula
WHERE
  id = 1;