【问题标题】:getting name and value from xmltype attribute in oracle从 oracle 中的 xmltype 属性获取名称和值
【发布时间】:2016-11-08 12:50:09
【问题描述】:

说明

您好,我在从 Oracle 中的 XMLType 值中提取属性名称和值时遇到问题。 基本上,我有一个表,比如说TableA,它有一个XMLType 列,我们称之为TableA_configTableA_config 中的值具有如下结构: <TableAConfig someAttribute1="value1" someAttribute2="value2" someAttribute3="value3" />。属性的数量及其名称可能会有所不同,并且事先不知道。 我需要做的是(为每一行)创建名为TableAConfigList 的新XMLElement,其中包含名为TableAConfig 的XMLElement,其中每个都有两个属性:namevalue。现在,TableAConfig 节点的数量必须等于TableA_config 列中的属性数量,并且每个节点在name 属性中保存相应属性的名称,在value 属性中保存其值。

示例

发件人:

<TableAConfig someAttribute1="value1" someAttribute2="value2" someAttribute3="value3" />

我应该得到:

<TableAConfigList>
    <TableAConfig name="someAttribute1" value="value1"/>
    <TableAConfig name="someAttribute2" value="value2"/>
    <TableAConfig name="someAttribute3" value="value3"/>
</TableAConfigList>

我尝试了什么

我想出了从TableA_config 列值创建XMLTable 的想法,并在其中创建两列,我以后可以选择它们。它看起来像这样(它是一个更大查询的片段):

SELECT XMLElement("TableAConfigList",
    (SELECT
        XMLAgg(
           XMLElement("TableAConfig",
                XMLAttributes(
                    tmp."attr_name" as "name",
                    tmp."attr_text" as "value"
                )
            )
        ) from XMLTable('/TableAConfig/@*'
            passing TableA.TableA_config
            columns
               "attr_name" varchar(30) path 'name()',
               "attr_text" varchar(30) path 'text()'
        ) tmp
    )
) from dual

但现在我明白了:

<TableAConfigList>
    <TableAConfig name="someAttribute1"></TableAConfig>
    <TableAConfig name="someAttribute2"></TableAConfig>
    <TableAConfig name="someAttribute3"></TableAConfig>
</TableAConfigList>

没有value。但是,如果我从XMLAttributes 中删除name,它就会出现。来自:

SELECT XMLElement("TableAConfigList",
    (SELECT
        XMLAgg(
           XMLElement("TableAConfig",
                XMLAttributes(
                    tmp."attr_text" as "value"
                )
            )
        ) from XMLTable('/TableAConfig/@*'
            passing TableA.TableA_config
            columns
               "attr_name" varchar(30) path 'name()',
               "attr_text" varchar(30) path 'text()'
        ) tmp
    )
) from dual

我明白了:

<TableAConfigList>
    <TableAConfig value="value1"></TableAConfig>
    <TableAConfig value="value2"></TableAConfig>
    <TableAConfig value="value3"></TableAConfig>
</TableAConfigList>

我认为可能由于某种原因,只能以这种方式创建一个属性,但如果我通过硬编码添加一个新属性,它会显示在结果中,如下所示:

SELECT XMLElement("TableAConfigList",
    (SELECT
        XMLAgg(
           XMLElement("TableAConfig",
                XMLAttributes(
                    tmp."attr_text" as "value",
                    'testValue' as "testAttribute"
                )
            )
        ) from XMLTable('/TableAConfig/@*'
            passing TableA.TableA_config
            columns
               "attr_name" varchar(30) path 'name()',
               "attr_text" varchar(30) path 'text()'
        ) tmp
    )
) from dual

结果:

<TableAConfigList>
    <TableAConfig value="value1" testAttribute="testValue"></TableAConfig>
    <TableAConfig value="value2" testAttribute="testValue"></TableAConfig>
    <TableAConfig value="value3" testAttribute="testValue"></TableAConfig>
</TableAConfigList>

XMLAttributes 两列和硬编码的一列都放入给我nametestAttribute,但没有value

有人能告诉我是因为我错过了一些非常明显的东西吗,是错误还是我做错了。我对 Oracle 和 PL/SQL 很陌生,非常感谢您的帮助。谢谢!

【问题讨论】:

    标签: sql xml oracle xpath plsql


    【解决方案1】:

    您的第一次尝试就快到了。在评估 XPath 时,当您位于带有/TableAConfig/@* 的属性列表中时,您不需要text() 来获取其中的属性值。您已经处于属性级别,因此仅对当前节点使用“点”. 就足够了。

    所以试试这样的 -

    SELECT XMLElement("TableAConfigList",
        (SELECT
            XMLAgg(
               XMLElement("TableAConfig",
                    XMLAttributes(
                        tmp."attr_name" as "name",
                        tmp."attr_text" as "value"
                    )
                )
            ) from XMLTable('/TableAConfig/@*'
                passing TableA.TableA_config
                columns
                   "attr_name" varchar(30) path 'name()',
                   "attr_text" varchar(30) path '.'
            ) tmp
        )
    ) from dual
    

    与您第一次尝试的唯一区别是value 属性的xpath。

    【讨论】:

    • 非常感谢,这行得通:)。在这里问了我的问题后,我做了一些试验和错误(出于绝望),结果发现 xpath '/' 也可以工作。 '.''/' 有什么区别吗?无论如何,接受答案:)
    • 是的。 '。'指向当前节点,'/'指向根节点。但是在这种情况下,由于我们已经在XMLTABLE 子句中向下遍历到属性级别,因此在我们已经使用/@* 处于属性级别之后,会评估PATH 子句(xpath)。所以当前节点也是剩余 XML 块的根节点。希望这是有道理的。
    【解决方案2】:

    你也可以使用XMLTRANSFORM

    select xmltransform(
           xmltype('<TableAConfig someAttribute1="value1" someAttribute2="value2" someAttribute3="value3" />'),
           xmltype('<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/">
            <xsl:for-each select="TableAConfig">
    <TableAConfigList>
                <xsl:for-each select="@*">
                    <xsl:element name="TableAConfig" >
                        <xsl:attribute name="name">
                            <xsl:value-of select="name()"/>
                        </xsl:attribute>
                        <xsl:attribute name="value">
                            <xsl:value-of select="."/>
                        </xsl:attribute>
                    </xsl:element>
                </xsl:for-each>
    </TableAConfigList>
            </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>'))
    from dual
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-06
      • 2011-10-02
      • 2018-11-16
      • 1970-01-01
      • 2019-08-19
      • 1970-01-01
      相关资源
      最近更新 更多