2014-06-09 25 views
0

我的工作,我需要返回元素名稱和值作爲鍵值對如下使用XQuery的要求。返回元素名稱和值的鍵值對

[代碼=第一數據,第二數據的LAST_UPDATE = value屬性等的123,px_last = value屬性]

存在與屬性值7數據元素內應當被理解爲與上面映射得到的第一場到第一數據並且第二映射到第二數據值屬性。 等。

有了您的幫助,我是能夠產生輸出卻得到了打,我需要第一數據屬性值的第一個字段元素映射等等等等

在此先感謝

XML文件:

<root> 
<fields> 
    <field>PX_LAST</field> 
    <field>LAST_UPDATE</field> 
    <field>LAST_UPDATE_DT</field> 
    <field>SECURITY_DES</field> 
    <field>FUT_CUR_GEN_TICKER</field> 
    <field>YLD_CNV_BID</field> 
    <field>YLD_CNV_ASK</field> 
</fields> 
<Datas> 
    <Data> 
     <code>0</code> 
     <ins> 
      <id>CT30</id> 
      <key>Govt</key> 
     <ins/> 
     <data value="98.843750"/> 
     <data value="16:14:45"> 
     </data> 
     <data value="06/03/2014"/> 
     <data value="T 3 3/8 05/15/44"/> 
     <data value=""/> 
     <data value="3.439"/> 
     <data value="3.437"/> 
    </Data> 
    <Data> 
     <code>0</code> 
     <ins> 
      <id>US0001W</id> 
      <key>Index</key> 
     <ins/> 
     <data value=".119000"/> 
     <data value="06:46"/> 
     <data value="06/03/2014"/> 
     <data value="ICE LIBOR USD 1 Week"/> 
     <data value=""/> 
     <data value="N.A."/> 
     <datavalue=".11900"></data> 
    </Data> 
</Datas> 
</root> 

的XQuery:

declare function xf:strip-namespace($e as element()) 
as element() 
{ 
element { xs:QName(local-name($e)) } 
{ 
    for $child in $e/(@*,node()) 
    return 
if ($child instance of element()) 
then 
    xf:strip-namespace($child) 
else 
    $child 
} 
}; 

let $nl := "&#10;" 

let $count := 0 

for $x in  doc("test.xml")/soap:Envelope/soap:Body/dlws:retrieveGetDataResponse/dlws:instrumentDatas//* 
let $y:=xf:strip-namespace($x) 
return 
if($y/name() = 'instrumentData') 
then 
concat($nl,'[','') 
else if($y/name()='data') 
then 
    concat($y/name(),'=',$y/data(@value),',') 
else if($y/name() != 'instrument') 
then 
    concat($y/name(),'=',$y/text(),',') 
else 
() 

立即輸出:

[code = 123,data = werr,data =「qwe」,data =「wer」,......,] [code = 456,data = rty,data = 「tyuu」,data =「uuu」,......,]

回答

2

一般來說,如果你可以將你的問題分解成更小的部分,它將促成一個更接近類似問題本身的簡單解決方案。

declare function local:make-pair(
    $e as element() 
) as xs:string? 
{ 
    typeswitch($e) 
    case element(data) return concat(local-name($e), '=', $e/@value) 
    default return concat(local-name($e), '=', $e) 
}; 

let $idatas := 
<idatas> 
<idata> 
    <code>123</code> 
    <data value="wer"></data> 
    <data value="sdf"></data> 
    <data value="zxc"></data> 
    <data value="asd"></data> 
    <data value="jgh"></data> 
    <data value="cvb"></data> 
    <data value="bsz"></data> 
</idata> 

<idata> 
    <code>345</code> 
    <data value="ff"></data> 
    <data value="zxd"></data> 
    <data value="wvver"></data> 
    <data value="wencvr"></data> 
    <data value="wzxcer"></data> 
    <data value="wmmer"></data> 
    <data value="wuuer"></data> 
</idata> 
</idatas> 
for $idata in $idatas/idata 
let $pairs := 
    for $p in $idata/* 
    return local:make-pair($p) 
return concat('[', string-join($pairs, ','), ']') 
+0

非常感謝您的幫助。今天我學到了一件新事物。 –

2

在回答以下幾個部分,我完全忽略了strip-namespace的一部分,這是一個不好的想法。 Eighter將其聲明爲默認名稱空間,不再擔心它,或者使用local-name()而不是名稱,或使用通配符名稱空間mather *:elementname*


輸入在問題更新期間被修改。直到下一個水平條的所有內容都是指問題的第一個修訂版本。

你可以使用一些的XQuery 3.0的特性,特別是呼籲在軸步驟的功能和字符串連接運算符||做所有的「字符串操作富」用很少的代碼:

//idata/(      (: for all idata elements :) 
    "[" || 
    string-join((    (: combine all key/value pairs with commata :) 
    "code=" || code/data(), (: code header :) 
    data/("data=" || @value)), (: data fields :) 
    ',') || 
    ']') 

正是適合Stack Overflow的一行(如果你真的想要的話)!

//idata/("["||string-join(("code="||code/data(),data/("data="||@value)),',')||']') 

隨着輸出是

[代碼= 123,數據= WER,數據= SDF,數據= ZXC,數據= ASD,數據= JGH,數據= CVB,數據= BSZ] [代碼= 345,數據= FF,數據= ZXD,數據= wvver,數據= wencvr,數據= wzxcer,數據= wmmer,數據= wuuer]

甲可能更可讀的版本與顯式循環,仍然使用連接操作符(在我看來,這增強了可讀性):

for $idata in $xml//idata 
return 
    "[" || string-join((
    "code=" || $idata/code/data(), 
    for $data in $idata/data 
    return 
     "data=" || $data/@value), 
    ',') || ']' 

對於更新問題,一個班輪將可能過於不可讀。修改後的代碼最後只加入數據元索引:

for $dataset in /root/Datas/Data 
return 
    "[" || string-join((
    "code=" || $dataset/code/data(), 
    for $data at $position in $dataset/data 
    let $field := /root/fields/field[$position] 
    return 
     $field || "=" || $data/@value), 
    ',') || ']' 
+0

非常感謝,我會按照你的建議。 –

+0

我能夠得到上面要求的數據,並且要感謝你們兩個,但現在變得越來越複雜,因爲要求映射字段如下 [code = 123,px_last = abc,last_update = ... ] [code = 4656,px_last = ttr,last_update = ...] 有7個數據元素,其屬性值insde ,應該讀作第一個字段名稱=第一個數據屬性值等等 即px_last = WER,LAST_UPDATE =自衛隊等每個數據 等 你的幫助再次非常感謝 –

+0

請張貼數據實際上代表您的問題(編輯你的問題),連同教人口會d輸出。 –