2013-03-21 73 views
1

我有一個非常複雜的XQuery來編寫(至少按照我的標準)。非常複雜的XQuery轉換

這是我的輸入XML:

<testRequest> 
    <request1> 
     <Line>1</Line> 
     <action>addtoName</action> 
    </request1> 
    <request2> 
     <Line>2</Line> 
     <action>addtoSpace</action> 
    </request2> 
    <request3> 
     <Line>3<Line> 
     <action>addtospace</action> 
    </request3> 
</testRequest> 

以我輸出XML,動作應附作爲屬性的「request1」元素。因此,基於request1元素下的動作元素,爲request1元素的屬性應爲下列之一:

if action = IgnoreCase(addtoName), the request1 element should be <request1 action=insertingname> 
if action = IgnoreCase(addtoSpace), the request1 element should be <request1 action=updatingspace> 

不僅如此,而且,我需要的屬性添加到元素,基於在它下面的動作值。 所以,我必須遍歷元素下的每個元素,看看是否有任何元素等於「addtospace」,如果是,那麼我需要獲取元素的相應值並組成元素的屬性。從上面的XML,我的用於元件屬性應該是,

<testRequest lineFiller="Line Like 2_* AND Line Like 3_*>, where 2 and 3 are the respective line numbers. 

和如果有與元件沒有元素= addtoSpace,則該元素的屬性應該被「改變」。

因此,總的來說,我轉換的XML應該是這樣的:

<testRequest lineFiller="Line Like 2_* AND Line Like 3_*> 
    <request1 action=insertingname> 
     <Line>1</Line> 
     <action>addtoName</action> 
    </request1> 
    <request2 action=updatingspace> 
     <Line>2</Line> 
     <action>addtoSpace</action> 
    </request2> 
    <request3 action=updatingspace> 
     <Line>3<Line> 
     <action>addtospace</action> 
    </request3> 
</testRequest> 

任何幫助來完成這個任務humungous將不勝感激。

謝謝!!!

+0

ridermule,使用XSLT進行此類處理會更容易。您對XSLT解決方案感興趣嗎? – 2013-03-22 03:40:04

+0

Dimitre,其實我對xslt非常熟悉......但不幸的是,上週有人打電話(當然不是我),我們應該只使用xqueries而不使用xslts。所以,我現在正在學習xqueries。 – ridermule 2013-03-22 13:58:14

+0

ridermule,你有我的同情心。也許有時間去找另一份工作? :) – 2013-03-22 14:37:44

回答

1

您應該定義函數來生成需要添加到元素中的屬性。

用於添加到「請求」元素,這應該工作:

declare function local:getaction($x) { 
    if (lower-case($x/action) = "addtoname") then attribute action {"insertingspace"} else 
    if (lower-case($x/action) = "addtospace") then attribute action {"updatingspace"} else 
() 
}; 

的linefiller屬性同樣可以創建:

declare function local:getfiller($x) { 
    attribute lineFiller { 
     if ($x/*[lower-case(action) = "addtospace"]) then 
      string-join(
      for $r in $x/*[lower-case(action) = "addtospace"] 
      return concat("Line Like ",$r/Line,"_*") 
      , " AND ") 
     else "change" 
     } 
}; 

然後把它放在一起,樂趣簡單的循環播放原始文檔,在需要的地方添加屬性:

let $doc:=<<your original document>> 

return 
<testRequest> 
{ local:getfiller($doc) } 
{ for $r in $doc/* return 
    element { name($r) } { 
    local:getaction($r), 
    $r/* 
    } 
} 
</testRequest> 

編輯:增強的getfiller功能,如果沒有任何操作,則返回「更改」

+0

嗨邪惡奧托,首先,非常感謝你的解決方案......它部分工作。不工作的部分是lineFiller部分。該函數似乎總是返回一個空字符串。另外,如果沒有稱爲「Addtospace」的元素,則該函數應該返回「已更改」。我現在被困在這裏。無論如何,非常感謝您的幫助!你真的很棒! – ridermule 2013-03-21 18:06:53

+0

如果沒有動作,我更新了'getfiller'函數來放入字符串。我不知道爲什麼這個函數不應該返回一些東西;我逐字從我的工作測試代碼複製它。你使用的是什麼xquery引擎? – 2013-03-21 23:05:24

+0

再次感謝你,邪惡的otto!該解決方案實際上工作......昨天是我的錯......我做了一些愚蠢的事情。我有最後一個請求。如果我想修改getfiller函數來測試「addtospace」和「addtoline」,並在兩種情況下都做同樣的事情,我該怎麼做?我厭倦這樣做:對於$ x/* [小寫(動作)=「addtospace」或「addtoline」]中的$ r,並在if語句中添加了同樣的內容,但這並不奏效。 – ridermule 2013-03-22 14:00:08