XQuery - перебирать каждый атрибут - PullRequest
2 голосов
/ 16 марта 2020

Я пытаюсь перебрать XML с этой структурой:

<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>

Я хочу провести l oop через столбцы и заменить некоторые ключевые слова, в частности атрибут caption. Например, я хочу заменить ключевое слово "Client" на "Cedent".

Я пытался написать что-то вроде этого:

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")
')

Но, конечно, я получаю ошибки, которые я ' я не уверен, как обойти:

XQuery [#data.data.modify()]: Syntax error near 'replace', expected 'where', '(stable) order by' or 'return'.

Я не очень знаком с XQuery. Может ли кто-нибудь помочь мне здесь?

Ответы [ 2 ]

2 голосов
/ 16 марта 2020
   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
0 голосов
/ 17 марта 2020

К сожалению, метод .modify() может обновлять только одно значение за раз.

Очень некрасиво из-за MS SQL Отсутствие поддержки на сервере последних стандартов w3 c для XQuery , Xpath , et c.

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;
...