Reputation: 21
I am trying to iterate over XML with this structure:
<Query id="Y120-M2-D1-H8-M42-S12-MS276-6676" name="Transactions_ModelGenerator_v_1.0.0.104">
<Description />
<Columns>
<Column caption="Client Code" sorting="None" sortIndex="-1">
<Expr class="ENTATTR" id="c.Number" />
</Column>
<Column caption="Client Name" sorting="None" sortIndex="-1">
<Expr class="ENTATTR" id="c.Name" />
</Column>
<Column caption="Market Code" sorting="None" sortIndex="-1">
<Expr class="ENTATTR" id="r.Number" />
</Column>
<Column caption="Market Name" sorting="None" sortIndex="-1">
<Expr class="ENTATTR" id="r.Name" />
</Column>
</Columns>
<JustSortedColumns />
<Conditions linking="All">
<Condition class="SMPL" enabled="True" readOnly="False">
<Operator id="Equal" />
<Expressions>
<Expr class="ENTATTR" id="c.Number" />
<Expr class="CONST" type="String" kind="Scalar" value="A1B" text="A1B" />
</Expressions>
</Condition>
<Condition class="SMPL" enabled="True" readOnly="False">
<Operator id="Equal" />
<Expressions>
<Expr class="ENTATTR" id="ConversionCurrency" />
<Expr class="CONST" type="String" kind="Scalar" value="EUR" text="EUR" />
</Expressions>
</Condition>
</Conditions>
</Query>
I want to loop through the Columns, and replace certain keywords, specifically the caption attribute. For example, I want to replace keyword "Client" with "Cedent".
I've tried writing something like this:
update #data
set data.modify('
for $col in /Query/Columns[1]/Column/caption
replace value of $col with fn:replace($col, "Client", "Cedent")
where fn:contains($col, "Client")
')
But of course I'm getting errors I'm not sure how to work around:
XQuery [#data.data.modify()]: Syntax error near 'replace', expected 'where', '(stable) order by' or 'return'.
I'm not very familiar with XQuery. Can somebody help me here?
Upvotes: 2
Views: 474
Reputation: 824
for $col in /Query/Columns[1]/Column/@caption[fn:contains(., "Client")]
let $x := fn:replace($col, "Client", "Cedent")
return replace value of node $col with $x
Upvotes: 2
Reputation: 22182
Unfortunately, .modify()
method can update just one value at a time.
Very ugly way due to MS SQL Server lack of support of the latest w3c standards for XQuery, Xpath, etc.
SQL
DECLARE @xml XML = N'<Query id="Y120-M2-D1-H8-M42-S12-MS276-6676" name="Transactions_ModelGenerator_v_1.0.0.104">
<Description/>
<Columns>
<Column caption="Client Code" sorting="None" sortIndex="-1">
<Expr class="ENTATTR" id="c.Number"/>
</Column>
<Column caption="Client Name" sorting="None" sortIndex="-1">
<Expr class="ENTATTR" id="c.Name"/>
</Column>
<Column caption="Market Code" sorting="None" sortIndex="-1">
<Expr class="ENTATTR" id="r.Number"/>
</Column>
<Column caption="Market Name" sorting="None" sortIndex="-1">
<Expr class="ENTATTR" id="r.Name"/>
</Column>
</Columns>
<JustSortedColumns/>
<Conditions linking="All">
<Condition class="SMPL" enabled="True" readOnly="False">
<Operator id="Equal"/>
<Expressions>
<Expr class="ENTATTR" id="c.Number"/>
<Expr class="CONST" type="String" kind="Scalar" value="A1B" text="A1B"/>
</Expressions>
</Condition>
<Condition class="SMPL" enabled="True" readOnly="False">
<Operator id="Equal"/>
<Expressions>
<Expr class="ENTATTR" id="ConversionCurrency"/>
<Expr class="CONST" type="String" kind="Scalar" value="EUR" text="EUR"/>
</Expressions>
</Condition>
</Conditions>
</Query>';
DECLARE @oldValue VARCHAR(10) = 'Client'
, @NewValue VARCHAR(10) = 'Cedent'
, @caption VARCHAR(30);
WHILE @xml.exist('/Query/Columns/Column[fn:contains(@caption, sql:variable("@oldValue"))]') = 1
BEGIN
SET @caption = @xml.value('(/Query/Columns/Column[fn:contains(@caption, sql:variable("@oldValue"))]/@caption)[1]','VARCHAR(30)');
SET @caption = REPLACE(@caption, @oldValue, @NewValue);
SET @xml.modify('replace value of
(/Query/Columns/Column[fn:contains(@caption, sql:variable("@oldValue"))]/@caption)[1] with (sql:variable("@caption"))');
END
-- after
SELECT @xml;
Upvotes: 0