sql server - T-SQL XPath query to join an Attribute from an ancestor to a child element -
i have following xml document fragments:
<document id="856" version="004010" direction="outbound"> <xpaths> <xpath id="deliveraddresscode">//ib//transaction[1]/loop[@loopid="n1"]/n1[n101="st"][n103="zz"]/n104/text()</xpath> </xpaths> <schema> <bsn bsn01="00" bsn02="{xpath::concat(substring(asn[1]/asnh[1]/senderid[1],1,5),asn[1]/asnh[1]/dino[1])}" bsn03="{xpath::.//asnh/date/text()}" bsn04="{xpath::.//asnh/time/text()}" /> <dtm dtm01="011" dtm02="{xpath::.//asnh/shipdate/text()}" /> <hl hl01="1" hl02="" hl03="s"> <td1 td101="plt" td102="{xpath::.//asnh/loadingqty/text()}" td103="" td104="" td105="" td106="n" td107="{xpath::.//asnh/zweight/text()}" td108="kg" /> <td5 td501="" td502="" td503="" td504="m" td505="{sql::select [dbo].[fslocaltoremotemapping]('{xpath::.//asnh/baanid/text()}','{xpath::.//asnh/isausageindicator}','forwardingagents','{xpath::.//asnh/cfrw/text()}')}" /> <td3 td301="tl" td302="" td303="{xpath::.//asnh/trackingno/text()}" /> <per per01="ic" per02="?" per03="em" per04="?@?.com" /> <n1 n101="sf" n102="{xpath:://sf/nama/text()}" n103="zz" n104="{xpath:://sf/cuno/text()}"> <n3_sf n301="{xpath:://sf/namc/text()}" /> <n4_sf n401="{xpath:://sf/cityname/text()}" n402="{xpath:://sf/prov/text()}" n403="{xpath:://sf/pstc/text()}" n404="{xpath:://sf/country/text()}" /> </n1> <n1 n101="st" n102="{xpath:://ib//transaction[1]/loop[@loopid='n1']/n1[n101='st'][n103='zz']/n102/text()}" n103="zz" n104="{xpath:://ib//transaction[1]/loop[@loopid='n1']/n1[n101='st'][n103='zz']/n104/text()}" /> </hl> </schema> <scripts> <function id="fcdec"> function fcdec(x) { if(x >= 3500.00) return "002" ; else return "002"; }</function> </scripts> </document>
and (fragment of above):
<schema> <bsn bsn01="00" bsn02="{xpath::concat(substring(asn[1]/asnh[1]/senderid[1],1,5),asn[1]/asnh[1]/dino[1])}" bsn03="{xpath::.//asnh/date/text()}" bsn04="{xpath::.//asnh/time/text()}" /> <dtm dtm01="011" dtm02="{xpath::.//asnh/shipdate/text()}" /> <hl hl01="1" hl02="" hl03="s"> <td1 td101="plt" td102="{xpath::.//asnh/loadingqty/text()}" td103="" td104="" td105="" td106="n" td107="{xpath::.//asnh/zweight/text()}" td108="kg" /> <td5 td501="" td502="" td503="" td504="m" td505="{sql::select [dbo].[fslocaltoremotemapping]('{xpath::.//asnh/baanid/text()}','{xpath::.//asnh/isausageindicator}','forwardingagents','{xpath::.//asnh/cfrw/text()}')}" /> <td3 td301="tl" td302="" td303="{xpath::.//asnh/trackingno/text()}" /> <per per01="ic" per02="? edi services" per03="em" per04="?@?.com" /> <n1 n101="sf" n102="{xpath:://sf/nama/text()}" n103="zz" n104="{xpath:://sf/cuno/text()}"> <n3_sf n301="{xpath:://sf/namc/text()}" /> <n4_sf n401="{xpath:://sf/cityname/text()}" n402="{xpath:://sf/prov/text()}" n403="{xpath:://sf/pstc/text()}" n404="{xpath:://sf/country/text()}" /> </n1> <n1 n101="st" n102="{xpath:://ib//transaction[1]/loop[@loopid='n1']/n1[n101='st'][n103='zz']/n102/text()}" n103="zz" n104="{xpath:://ib//transaction[1]/loop[@loopid='n1']/n1[n101='st'][n103='zz']/n104/text()}" /> </hl> </schema>
how retrieve document id first fragment second 1 query result is:
<schema id="856"> <bsn bsn01="00" bsn02="{xpath::concat(substring(asn[1]/asnh[1]/senderid[1],1,5),asn[1]/asnh[1]/dino[1])}" bsn03="{xpath::.//asnh/date/text()}" bsn04="{xpath::.//asnh/time/text()}" /> <dtm dtm01="011" dtm02="{xpath::.//asnh/shipdate/text()}" /> <hl hl01="1" hl02="" hl03="s"> <td1 td101="plt" td102="{xpath::.//asnh/loadingqty/text()}" td103="" td104="" td105="" td106="n" td107="{xpath::.//asnh/zweight/text()}" td108="kg" /> <td5 td501="" td502="" td503="" td504="m" td505="{sql::select [dbo].[fslocaltoremotemapping]('{xpath::.//asnh/baanid/text()}','{xpath::.//asnh/isausageindicator}','forwardingagents','{xpath::.//asnh/cfrw/text()}')}" /> <td3 td301="tl" td302="" td303="{xpath::.//asnh/trackingno/text()}" /> <per per01="ic" per02="? edi services" per03="em" per04="?@?.com" /> <n1 n101="sf" n102="{xpath:://sf/nama/text()}" n103="zz" n104="{xpath:://sf/cuno/text()}"> <n3_sf n301="{xpath:://sf/namc/text()}" /> <n4_sf n401="{xpath:://sf/cityname/text()}" n402="{xpath:://sf/prov/text()}" n403="{xpath:://sf/pstc/text()}" n404="{xpath:://sf/country/text()}" /> </n1> <n1 n101="st" n102="{xpath:://ib//transaction[1]/loop[@loopid='n1']/n1[n101='st'][n103='zz']/n102/text()}" n103="zz" n104="{xpath:://ib//transaction[1]/loop[@loopid='n1']/n1[n101='st'][n103='zz']/n104/text()}" /> </hl> </schema>
the query used
--alter function [dbo].[fxdocschema](@env varchar(10),@baanid varchar(10),@docid varchar(10)) returns xml begin declare @baanid varchar(10)='010-000164',@env varchar(10)='test',@docid varchar(10)='856' --return( select t.c.query('.') ,t.c.query('schema') (select meta edimeta baanid=@baanid , env=case lower(@env) when 't' 'test' when 'p' 'production' else @env end) f(x) cross applyx.nodes('meta/partners/partner/documents/document[@id=sql:variable("@docid")]') t(c) --) end
something this?
declare @xml xml = n'<document id="856" version="004010" direction="outbound"> <xpaths> <xpath id="deliveraddresscode">//ib//transaction[1]/loop[@loopid="n1"]/n1[n101="st"][n103="zz"]/n104/text()</xpath> </xpaths> <schema> <bsn bsn01="00" bsn02="{xpath::concat(substring(asn[1]/asnh[1]/senderid[1],1,5),asn[1]/asnh[1]/dino[1])}" bsn03="{xpath::.//asnh/date/text()}" bsn04="{xpath::.//asnh/time/text()}" /> <dtm dtm01="011" dtm02="{xpath::.//asnh/shipdate/text()}" /> <hl hl01="1" hl02="" hl03="s"> <td1 td101="plt" td102="{xpath::.//asnh/loadingqty/text()}" td103="" td104="" td105="" td106="n" td107="{xpath::.//asnh/zweight/text()}" td108="kg" /> <td5 td501="" td502="" td503="" td504="m" td505="{sql::select [dbo].[fslocaltoremotemapping](''{xpath::.//asnh/baanid/text()}'',''{xpath::.//asnh/isausageindicator}'',''forwardingagents'',''{xpath::.//asnh/cfrw/text()}'')}" /> <td3 td301="tl" td302="" td303="{xpath::.//asnh/trackingno/text()}" /> <per per01="ic" per02="?" per03="em" per04="?@?.com" /> <n1 n101="sf" n102="{xpath:://sf/nama/text()}" n103="zz" n104="{xpath:://sf/cuno/text()}"> <n3_sf n301="{xpath:://sf/namc/text()}" /> <n4_sf n401="{xpath:://sf/cityname/text()}" n402="{xpath:://sf/prov/text()}" n403="{xpath:://sf/pstc/text()}" n404="{xpath:://sf/country/text()}" /> </n1> <n1 n101="st" n102="{xpath:://ib//transaction[1]/loop[@loopid=''n1'']/n1[n101=''st''][n103=''zz'']/n102/text()}" n103="zz" n104="{xpath:://ib//transaction[1]/loop[@loopid=''n1'']/n1[n101=''st''][n103=''zz'']/n104/text()}" /> </hl> </schema> <scripts> <function id="fcdec"> function fcdec(x) { if(x >= 3500.00) return "002" ; else return "002"; }</function> </scripts> </document>' select x.value('@id', 'int') "@id" , ( select y.query('.') "*" @xml.nodes('document/schema/*') a(y) xml path(''), type ) @xml.nodes('document') a(x) xml path('schema')
five principles:
- i isolate main level of want @ root main query(the outer a(x) root of 'document')
- i isolate children(a(y)) , query on children of document/schema/*. if ran inner see children nodes on 3 rows.
- i don't care them use query of parts , label them text "*".
- i specify type of xml in nested select don't want give level on it, keep itself. (for xml path(''), type)
- i set attribute main id again , xml expression path ignore root setting (for xml path('schema'))
Comments
Post a Comment