在Oracle SQL中查询XML对象:通过指定对象的另一个属性来获取属性的值

时间:2017-03-24 20:34:17

标签: sql xml oracle xpath xmltype

我知道这里有很多关于在Oracle SQL中查询XML对象的条目。但是,我仍然无法在我的问题上找到任何答案。

我有一个SQL表obj,其中包含一些列。 XML格式的clob对象(列称为definition)。

我想从clob中提取一个具体的值。

XML看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
    <m>
        <i n="Status">0</i>
        <s n="Description">AmountDifference</s>
        <s n="Name">InputvsOutput</s>
        <a n="Variables">
            <m>
                <s n="Name">Formula</s>
                <s n="Value">B-A</s>
            </m>
            <m>
                <s n="Name">CriticalDiff</s>
                <s n="Value">abs({B} - {A}) &lt; 10</s>
            </m>
        </a>
    </m>

SQL查询应返回两个值:DescriptionValue,其中Name = CriticalDiff。

SQL查询的部分如下所示:

CAST(
CASE WHEN obj.definition is not null then
       UTL_I18N.UNESCAPE_REFERENCE(
                XMLTYPE(obj.definition).
                EXTRACT('//s[@n="Description"]/text()')
                .getStringVal() )
END as varchar(200)) as "Rule Expression"
, obj.definition as rule_xml

CAST块工作正常,但我想知道如何以类似的方式转换最后一个命令,以便我得到一个名称(= CriticalDiff)的值。

我面临的困难是有两个相似的元素(m)具有相同的属性名称(名称,值)。

我有什么想法可以从“CriticalDiff”获得“Value” - 属性吗?

提前致谢!

1 个答案:

答案 0 :(得分:0)

尝试:

WITH obj AS (
SELECT q'[<?xml version="1.0" encoding="UTF-8"?>
    <m>
        <i n="Status">0</i>
        <s n="Description">AmountDifference</s>
        <s n="Name">InputvsOutput</s>
        <a n="Variables">
            <m>
                <s n="Name">Formula</s>
                <s n="Value">B-A</s>
            </m>
            <m>
                <s n="Name">CriticalDiff</s>
                <s n="Value">abs({B} - {A}) &lt; 10</s>
            </m>
        </a>
    </m>]' as definition FROM dual
) SELECT 
  XMLTYPE( obj.definition ). 
    EXTRACT('//s[@n="Description"]/text()').getStringVal() as Description,
  XMLTYPE( obj.definition ). 
    EXTRACT('//m/s[@n="Name" and text() = "CriticalDiff"]/text()').getStringVal() as Name,
  UTL_I18N.UNESCAPE_REFERENCE(XMLTYPE( obj.definition ). 
    EXTRACT('//m/s[@n="Name" and text() = "CriticalDiff"]/../s[@n="Value"]/text()').getStringVal()) as Value
FROM obj;
DESCRIPTION      |NAME         |VALUE               |
-----------------|-------------|--------------------|
AmountDifference |CriticalDiff |abs({B} - {A}) < 10 |

xpath的另一个版本也可以使用:

 EXTRACT('//m[s[@n="Name" and text() = "CriticalDiff"]]/s[@n="Value"]/text()').getStringVal()) as Value