Как получить атрибут только с помощью xQuery

У меня есть функция, аналогичная следующей, возвращающая большой кусок xml (в производственной среде). На разных этапах приложения нам нужно извлечь из этого только некоторые элементы или только некоторые атрибуты.

create function testrig.fxConfigurations(@context varchar(300)) returns xml as 
begin
return (select 
'<configurations realm="configuration">
    <context name="apera">
        <backends>
            <backend name="Hades">
                <os>HP Unix</os>
                <ip>nnn.nnn.nnn</ip>
                <db vender="Oracle" version="11g">
                    <netconnect>Data Source= (DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = hades)(PORT = 1521)(RECV_BUF_SIZE=1048576))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = baan)));Password=********;User ID=ItsMe;" providerName="Oracle.DataAccess.Client"
                    </netconnect>
                </db>
            </backend>
            <backend name="Athena">
                <os>HP Unix</os>
                <ip>nnn.nnn.nnn</ip>
                <db vender="Oracle" version="11g">
                    <netconnect>Data Source= (DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = hades)(PORT = 1521)(RECV_BUF_SIZE=1048576))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = baan)));Password=********;User ID=ItsMe;" providerName="Oracle.DataAccess.Client"
                    </netconnect>
                </db>
            </backend>
        </backends>
    </context>
</configurations>
')

end 
go

Как получить только имя атрибута, то есть «Аид», «Афина», используя xQuery, подобный этому

select (testrig.fxConfigurations(null).query('configurations/context[@name="apera"]/backends').query('/descendant-or-self::*'))

person TonyP    schedule 05.04.2014    source источник


Ответы (1)


Если вы хотите объединить все значения атрибутов backend/@name (аля GROUP_CONCAT):

select testrig.fxConfigurations(null)
   .query('data(configurations/context[@name="apera"]/backends/backend/@name)')

Если вам нужно работать с атрибутами по отдельности, вам может понадобиться использовать nodes для их извлечения:

WITH cteXml AS
(
    SELECT testrig.fxConfigurations(null)
           .query('configurations/context[@name="apera"]') as context
)
SELECT Nodes.node.value('@name', 'varchar(50)') AS backEndName
FROM cteXml
    CROSS APPLY cteXml.context.nodes('//backends/backend') as Nodes(node);

Поиграйте здесь

person StuartLC    schedule 05.04.2014
comment
Спасибо StuartLC, именно то, что мы хотели. - person TonyP; 05.04.2014