Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse an XML string in MySQL

Tags:

mysql

xml

xpath

I have a task of parsing a simple XML-formatted string in a MySQL stored procedure. XML looks like this (testing purposes only):

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

What I need MySQL to do is to produce a result set one row per match. My stored proc code looks like this:

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

What this does, however, is it concatenate all the matches, producing "Example 1 Example 2". This is, by the way, documented, but quite useless behavior.

What can I do to make it return the matches in rows without having to count the matches and processing them one-by-one? Is it even possible with MySQL?

Thanks all!

like image 240
MK_Dev Avatar asked May 23 '09 22:05

MK_Dev


People also ask

Does MySQL support XML data type?

XML SupportAurora MySQL supports two XML functions: ExtractValue and UpdateXML . ExtractValue accepts an XML document, or fragment, and an XPATH expression. The function returns the character data of the child or element matched by the XPATH expression.

Can you import XML into MySQL?

To import data from a XML file into a MySQL table, select the table in Object Browser and select Table -> Import -> Import XML Data Using Load Local... or(Ctrl+Shift+X). Tables: The list of all tables of the currently active database is shown. Select the Table from the list box.

How to store XML data in MySQL?

The most common way to store XML in MySQL is to use the LOAD_FILE() function to open an entire XML document, store it in a variable, and insert the variable into a table column.

Can we use both XML and MySQL together?

You can use XML from within any language that has the appropriate processing tools available. For example, XML APIs exist for languages such as PHP, Python, Java, and Tcl, all of which also have MySQL capabilities.


2 Answers

This needs a rowset generation function, and MySQL lacks it.

You can use a dummy table or a subquery instead:

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

Note that support for session variables in XPath is broken in 5.2 (but works fine in 5.1)

like image 107
Quassnoi Avatar answered Oct 05 '22 14:10

Quassnoi


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

Alternatively...

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

Sorry if the syntax is a bit shakey in here, not much of a mysql guru...

like image 36
Tracker1 Avatar answered Oct 05 '22 13:10

Tracker1