2009-05-23 4 views
7

У меня есть задача разбора простой XML-форматированной строки в хранимой процедуре MySQL. XML выглядит так (только для целей тестирования):Анализ XML-строки в MySQL

<parent> 
    <child>Example 1</child> 
    <child>Example 2</child> 
</parent> 

Что мне нужно для выполнения MySQL, так это создать набор результатов по одной строке в каждом матче. Мой сохраненный код прок выглядит следующим образом:

DECLARE xmlDoc TEXT; 
SET xmlDoc = '<parent><child>Example 1</child><child>Example 2</child></parent>'; 
SELECT ExtractValue(xmlDoc, '//child'); 

Что это делает, однако, это сцепить все матчи, производя «Пример 1 Пример 2». Это, кстати, документированное, но совершенно бесполезное поведение.

Что я могу сделать, чтобы вернуть спички в строках без необходимости подсчитывать совпадения и обрабатывать их один за другим? Возможно ли это с MySQL?

Спасибо всем!

ответ

7
DECLARE i INT DEFAULT 1; 
DECLARE count DEFAULT ExtractValue(xml, 'count(//child)'); 

WHILE i <= count DO 
    SELECT ExtractValue(xml, '//child[$i]'); 
    SET i = i+1; 
END WHILE 

В качестве альтернативы ...

DECLARE v VARCHAR(500) DEFAULT ''; 
DECLARE i INT DEFAULT 1; 

REPEAT 
    SET v = ExtractValue(xml, '//child[$i]') 
    SET i = i+1; 
    IF v IS NOT NULL THEN 
     -- do something with v 
    END IF 
UNTIL v IS NULL 

К сожалению, если синтаксис немного Шеки здесь, не так много тузд гуру ...

8

Это нуждается в функции генерации набора строк, и MySQL не хватает.

Вы можете использовать фиктивный таблицу или подзапрос вместо:

SELECT ExtractValue(@xml, '//mychild[[email protected]]'), 
     @r := @r + 1 
FROM (
     SELECT @r := 1 
     UNION ALL 
     SELECT 1 
     ) vars 

Отметим, что поддержка переменных сеанса в XPath сломана 5.2 (но отлично работает в 5.1)

+0

Это работает довольно хорошо. Благодарю. –

+0

Используя этот запрос, я получаю только две строки. Я что-то упускаю? – reticent

+0

@reticent: как было сказано ранее, 'MySQL' не имеет функции генерации ряда. Подзапрос возвращает только 2 строки, которые вы получаете. Добавьте несколько строк в 'vars' (или замените его« SELECT »из таблицы достаточно большим). – Quassnoi

1

Ниже хранимая процедура пример для чтения XML с помощью время цикла

-- drop procedure testabk; 
-- call testabk(); 
delimiter // 
create procedure testabk() 
begin 

DECLARE k INT UNSIGNED DEFAULT 0; 
DECLARE xpath TEXT; 
declare doc varchar(1000); 
DECLARE row_count1 INT UNSIGNED; 

set doc='<StaticAttributesBM><AttributeId id="11">Status</AttributeId><AttributeId id="2">Reason</AttributeId><AttributeId id="3">User Remarks</AttributeId></StaticAttributesBM>'; 
DROP TABLE IF EXISTS tempStaticKeywords; 
CREATE TABLE tempStaticKeywords(id int, staticKeywords VARCHAR(500)); 
SET row_count1 := extractValue(doc,'count(/StaticAttributesBM/AttributeId)'); 
select row_count1; 

-- iterate over books 
WHILE k < row_count1 DO   
    SET k := k + 1; 
    SET xpath := concat('/StaticAttributesBM/AttributeId[', k, ']'); 
    INSERT INTO tempStaticKeywords(id,staticKeywords) VALUES (
     extractValue(doc, concat(xpath,'/@id')), 
     extractValue(doc, xpath)  
    ); 
END WHILE; 

select * from tempStaticKeywords; 

END 
// 

Выход находится ниже

ID staticKeywords

1 Статус

2 Причина

3 Пользователь Замечания

Смежные вопросы