我是Xpath的新手,这是我的XML。我试图在appl / * __ job标记中获取属性值@name,并在节点snmp_notify / message中获取值' TESTQUEUE'并且我在一个步骤中迈出了一步时间。截至目前,我能够获取所有_job的子节点,但我无法获取node / snmp_notifylist / snmp_notify / message中的值。这是SQL,有人可以帮我识别我遇到的问题。
这是在表TAB_AR中存储为DEFINITION的样本XML文档。
<appl xmlns="http://dto.wa.ca.com/application" name="TEST_NEW_AGENT">
<version>12.0</version>
<comment />
<unix_job name="TEST_JOB">
<dependencies><relcount>0</relcount></dependencies>
<snmp_notifylist>
<snmp_notify>
<returncode>4</returncode>
<monitor_states><monitor_state>FAILED</monitor_state></monitor_states>
<snmpagent />
<message>TICKET TESTQUEUE TSTMSG</message>
</snmp_notify>
</snmp_notifylist>
</unix_job>
<link name="HOLD_LINK">
<dependencies><relcount>0</relcount></dependencies>
<hold>true</hold>
<job_ancestor_wait_default_ignore>true</job_ancestor_wait_default_ignore>
</link>
<sftp_job name="TEST_SFTP1">
<dependencies><relcount>0</relcount></dependencies>
<snmp_notifylist>
<snmp_notify>
<returncode>4</returncode>
<monitor_states>
<monitor_state>FAILED</monitor_state>
</monitor_states>
<snmpagent />
<message>TICKET MFG1AWA TSTMSG</message>
</snmp_notify>
</snmp_notifylist>
</sftp_job>
</appl>
这是我写的SQL,
SELECT
SFTP_Job_name = DEFT1.value('(@name)[1]','nvarchar(max)'),
Server_Address = DEFT1.query('local-name(/*:snmp_notifylist/*:snmp_notify/*:message)')
from (select CAST([DEFINITION] as XML) as DEFT from TAB_AR)TAB
CROSS APPLY TAB.DEFT.nodes('/*:appl/*[fn:contains(local-name(),"_job")]') as XMLTAB1(DEFT1)
答案 0 :(得分:1)
这似乎有效:
with xmlnamespaces (default 'http://dto.wa.ca.com/application')
select j.c.value('./@name', 'sysname') as [JobName],
m.c.value('./text()[1]', 'varchar(max)') as [MessageText]
from (
select cast(t.[Definition] as xml) as [Deft] from tab_ar t
) sq
cross apply sq.Deft.nodes('/appl/*[fn:contains(local-name(),"_job")]') j(c)
cross apply j.c.nodes('./snmp_notifylist/snmp_notify/message') m(c);
之后,用空格分割字符串并取中间部分应该是相对微不足道的。
答案 1 :(得分:1)
你很亲密......
在这一行中,我不确定,你真正想要的是什么:
DEFT1.query('local-name(/*:snmp_notifylist/*:snmp_notify/*:message)')
使用local-name()
,您可以返回一个特定节点的名称。当您从几个以_job
结尾的节点读取时,返回您正在读取的元素的名称是完全有意义的。
但是你告诉我们,你也试图阅读<message>
。可能是,你在一行中混合两个电话?
我稍微修改了你的代码:
SELECT
SFTP_Job_name = DEFT1.value('(@name)[1]','nvarchar(max)')
,NodeName = DEFT1.value('local-name(.)','nvarchar(max)')
,Server_Address = DEFT1.value('(*:snmp_notifylist/*:snmp_notify/*:message)[1]','nvarchar(max)')
from (select CAST([DEFINITION] as XML) as DEFT from TAB_AR)TAB
CROSS APPLY TAB.DEFT.nodes('/*:appl/*[fn:contains(local-name(.),"_job")]') as XMLTAB1(DEFT1);
返回
SFTP_Job_name NodeName Server_Address
TEST_SFTP1 sftp_job TICKET MFG1AWA TSTMSG
TEST_JOB unix_job TICKET TESTQUEUE TSTMSG
就像Roger Wolf指出的那样,最好使用如下指定的命名空间进行读取:
WITH XMLNAMESPACES (default 'http://dto.wa.ca.com/application')
SELECT
SFTP_Job_name = DEFT1.value('(@name)[1]','nvarchar(max)')
,NodeName = DEFT1.value('local-name(.)','nvarchar(max)')
,Server_Address = DEFT1.value('(snmp_notifylist/snmp_notify/message)[1]','nvarchar(max)')
from (select CAST([DEFINITION] as XML) as DEFT from TAB_AR)TAB
CROSS APPLY TAB.DEFT.nodes('/appl/*[fn:contains(local-name(.),"_job")]') as XMLTAB1(DEFT1);
一般规则是:尽可能具体!
如果您可以更改此设置,则应将XML存储在XML
类型的列中。
这个结构from (select CAST([DEFINITION] as XML) as DEFT from TAB_AR)TAB
应该没有必要......
可能,您的专栏实际上是XML
,而您只是不知道如何转移您在某处找到的代码以获得.nodes()
的正确语法?在这种情况下,试试这个:
SELECT
SFTP_Job_name = DEFT1.value('(@name)[1]','nvarchar(max)')
,NodeName = DEFT1.value('local-name(.)','nvarchar(max)')
,Server_Address = DEFT1.value('(*:snmp_notifylist/*:snmp_notify/*:message)[1]','nvarchar(max)')
from TAB_AR
CROSS APPLY TAB_AR.[DEFINITION].nodes('/*:appl/*[fn:contains(local-name(.),"_job")]') as XMLTAB1(DEFT1);