如何在标签的 url 部分提取 Oracle XML
How to extract Oracle XML when url part of tag
我对 XML 的了解还不够,不知道使用什么术语来提问。我将混淆我正在尝试解码的 XML 片段,希望不会混淆到使问题无法回答的地步。
我有一些 XML,我想获取值“要获取的第一个字符串”和“要获取的第二个字符串”。我如何编写 Oracle 查询来获取它们?
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
如果我编写一个 XML 查询并放入整个标记,如果其中一些字段发生变化会怎样?所以我认为我应该能够仅指示“ora:itemType”和“ora:billFactor”,而基本上忽略其余部分,对吗?
这个returns空:
with test_table(xmldata) as (
select
q'[
<root>
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
</itemTypes>
</root>
]'
from dual
)
select
xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/ora:itemType/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res
from test_table
;
URL 是一个命名空间。您可以在 XPath 中声明它。但是 ora
似乎是保留的,因为它仍然为空,因此您可以将其更改为其他内容(仅在查询中,而不是在 XML 文档中):
'declare namespace xyz="http://www.oracle.com/something/somethingelse";
/root/itemTypes/itemTypesList/xyz:itemType'
所以在上下文中:
select
xmlcast(
xmlquery(
'declare namespace xyz="http://www.oracle.com/something/somethingelse";
/root/itemTypes/itemTypesList/xyz:itemType'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res
from test_table
因为您想要多个值,所以您最好使用 XMLTable:
select x.*
from test_table tt
cross join xmltable(
xmlnamespaces('http://www.oracle.com/something/somethingelse' as "xyz"),
'/root/itemTypes/itemTypesList'
passing xmltype(tt.xmldata)
columns first_str varchar2(30) path 'xyz:itemType',
second_str varchar2(30) path 'xyz:billFactor'
) x
第一个变体(使用带 xpath 过滤器的 xmlquery):
with test_table(xmldata) as (
select
q'[
<root>
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
</itemTypes>
</root>
]'
from dual
)
select
xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:itemType[namespace-uri()="http://www.oracle.com/something/somethingelse"]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res1
,xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:billFactor[namespace-uri()="http://www.oracle.com/something/somethingelse"]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res2
from test_table
/
结果:
RES1 RES2
------------------------------ ------------------------------
First String to Get Second String to Get
NB 你的元素在 xmlnamespace 'ora',所以你需要指定它,但是因为 xmlquery 没有 XMLNAMESPACES参数,您有 2 个选择来指定它们:
- 在您的 xquery 的开头添加 xmlnamespace 声明:
'declare namespace ora = "http://www.oracle.com/something/somethingelse";...
- 或使用函数
namespace-uri()
: 过滤元素
*:itemType[namespace-uri()="http://www.oracle.com/something/somethingelse"]
*:element
意味着您需要来自任何 xml 命名空间的 element
。 [namespace-uri()="..."]
按命名空间过滤元素。
第二种变体:usint xmltable(xmlnamespaces(...)...)
with test_table(xmldata) as (
select
q'[
<root>
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
</itemTypes>
</root>
]'
from dual
)
select
xx.*
from test_table
,xmltable(
xmlnamespaces('http://www.oracle.com/something/somethingelse' as "ORA", default ''),
'/root/itemTypes/itemTypesList'
passing xmltype(xmldata)
columns
res1 varchar2(100) path 'ORA:itemType/text()'
,res2 varchar2(100) path 'ORA:billFactor/text()'
) xx
;
结果:
RES1 RES2
------------------------------ ------------------------------
First String to Get Second String to Get
1 row selected.
还有一些基于通配符命名空间和过滤器的较短变体:
select
xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:itemType[namespace-uri()!=""]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res1
,xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:billFactor[2]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res2
from test_table
第一个 returns 具有非空命名空间 uri 的元素,第二个 returns 第二个 billFactor 没有按命名空间过滤
我对 XML 的了解还不够,不知道使用什么术语来提问。我将混淆我正在尝试解码的 XML 片段,希望不会混淆到使问题无法回答的地步。
我有一些 XML,我想获取值“要获取的第一个字符串”和“要获取的第二个字符串”。我如何编写 Oracle 查询来获取它们?
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
如果我编写一个 XML 查询并放入整个标记,如果其中一些字段发生变化会怎样?所以我认为我应该能够仅指示“ora:itemType”和“ora:billFactor”,而基本上忽略其余部分,对吗?
这个returns空:
with test_table(xmldata) as (
select
q'[
<root>
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
</itemTypes>
</root>
]'
from dual
)
select
xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/ora:itemType/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res
from test_table
;
URL 是一个命名空间。您可以在 XPath 中声明它。但是 ora
似乎是保留的,因为它仍然为空,因此您可以将其更改为其他内容(仅在查询中,而不是在 XML 文档中):
'declare namespace xyz="http://www.oracle.com/something/somethingelse";
/root/itemTypes/itemTypesList/xyz:itemType'
所以在上下文中:
select
xmlcast(
xmlquery(
'declare namespace xyz="http://www.oracle.com/something/somethingelse";
/root/itemTypes/itemTypesList/xyz:itemType'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res
from test_table
因为您想要多个值,所以您最好使用 XMLTable:
select x.*
from test_table tt
cross join xmltable(
xmlnamespaces('http://www.oracle.com/something/somethingelse' as "xyz"),
'/root/itemTypes/itemTypesList'
passing xmltype(tt.xmldata)
columns first_str varchar2(30) path 'xyz:itemType',
second_str varchar2(30) path 'xyz:billFactor'
) x
第一个变体(使用带 xpath 过滤器的 xmlquery):
with test_table(xmldata) as (
select
q'[
<root>
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
</itemTypes>
</root>
]'
from dual
)
select
xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:itemType[namespace-uri()="http://www.oracle.com/something/somethingelse"]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res1
,xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:billFactor[namespace-uri()="http://www.oracle.com/something/somethingelse"]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res2
from test_table
/
结果:
RES1 RES2
------------------------------ ------------------------------
First String to Get Second String to Get
NB 你的元素在 xmlnamespace 'ora',所以你需要指定它,但是因为 xmlquery 没有 XMLNAMESPACES参数,您有 2 个选择来指定它们:
- 在您的 xquery 的开头添加 xmlnamespace 声明:
'declare namespace ora = "http://www.oracle.com/something/somethingelse";...
- 或使用函数
namespace-uri()
: 过滤元素
*:itemType[namespace-uri()="http://www.oracle.com/something/somethingelse"]
*:element
意味着您需要来自任何 xml 命名空间的 element
。 [namespace-uri()="..."]
按命名空间过滤元素。
第二种变体:usint xmltable(xmlnamespaces(...)...)
with test_table(xmldata) as (
select
q'[
<root>
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
</itemTypes>
</root>
]'
from dual
)
select
xx.*
from test_table
,xmltable(
xmlnamespaces('http://www.oracle.com/something/somethingelse' as "ORA", default ''),
'/root/itemTypes/itemTypesList'
passing xmltype(xmldata)
columns
res1 varchar2(100) path 'ORA:itemType/text()'
,res2 varchar2(100) path 'ORA:billFactor/text()'
) xx
;
结果:
RES1 RES2
------------------------------ ------------------------------
First String to Get Second String to Get
1 row selected.
还有一些基于通配符命名空间和过滤器的较短变体:
select
xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:itemType[namespace-uri()!=""]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res1
,xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:billFactor[2]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res2
from test_table
第一个 returns 具有非空命名空间 uri 的元素,第二个 returns 第二个 billFactor 没有按命名空间过滤