您好,我在Oracle中从XMLType值中提取属性名称和值时遇到问题。
基本上,我有一张表,让我们说TableA
,它有一个XMLType列,让我们称之为TableA_config
。 TableA_config
中的值具有以下结构:
<TableAConfig someAttribute1="value1" someAttribute2="value2" someAttribute3="value3" />
。属性的数量及其名称可能会有所不同,并且事先不知道。
我需要做的是(对于每一行)创建名为TableAConfigList
的新XMLElement,其中包含名为TableAConfig
的XMLElements,每个属性都有两个属性:name
和value
。现在,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>
我想出了从XMLTable
列值创建TableA_config
的想法,并在其中创建了两列,我可以稍后选择。它看起来像这样(它是一个更大的查询的片段):
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
。但是,如果我从name
移除XMLAttributes
,则会显示。从:
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
两列和硬编码列放入name
和testAttribute
,但没有value
。
有人能告诉我是因为我错过了一些非常明显的东西,这是一个错误还是我完全错了。我是Oracle和PL / SQL的新手,非常感谢您的帮助。谢谢!
答案 0 :(得分:1)
你的第一次尝试几乎就在那里。在评估XPath时,当您使用/TableAConfig/@*
进入属性列表时,您不需要text()
来获取其中的属性值。您已经处于属性级别,因此仅使用&#34; dot&#34; <{1}}对于当前节点就足够了。
所以尝试这样的事情 -
.
与您第一次尝试的唯一区别是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
属性的xpath。
答案 1 :(得分:0)
您也可以使用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