Удалить узел на основе значения атрибута другого узла

У меня есть следующий XML, возвращаемый в SQL, и я хотел бы использовать SQL XML DML для условного удаления узла на основе значения другого узла. В моем примере я хотел бы удалить узел «Цвет», когда значение атрибута «Значение» узла «Размер» равно «S».

<root>
            <ParentGroup>
                            <ChildGroup Id="1">
                                            <Child Id="1">
                                                            <Color Value="Red"/>
                                                            <Size Value="L"/>
                                            </Child>
                                            <Child Id="2">
                                                            <Color Value="Blue"/>
                                                            <Size Value="S"/>
                                            </Child>
                            </ChildGroup>
                            <ChildGroup Id="2">
                                            <Child Id="5">
                                                            <Color Value="Blue"/>
                                                            <Size Value="L"/>
                                            </Child>
                                            <Child Id="9">
                                                            <Color Value="Red"/>
                                                            <Size Value="S"/>
                                            </Child>
                            </ChildGroup>
            </ParentGroup>
</root>

Я хотел бы, чтобы полученный XML был:

<root>
            <ParentGroup>
                            <ChildGroup Id="1">
                                            <Child Id="1">
                                                            <Color Value="Red"/>
                                                            <Size Value="L"/>
                                            </Child>
                                            <Child Id="2">
                                                            <Size Value="S"/>
                                            </Child>
                            </ChildGroup>
                            <ChildGroup Id="2">
                                            <Child Id="5">
                                                            <Color Value="Blue"/>
                                                            <Size Value="L"/>
                                            </Child>
                                            <Child Id="9">
                                                            <Size Value="S"/>
                                            </Child>
                            </ChildGroup>
            </ParentGroup>
</root>

Заранее спасибо!


person silverbullettruck2001    schedule 07.05.2018    source источник


Ответы (1)


Вы можете использовать predicate, чтобы уменьшить <Child>-узлы до списка, который выполняет ваше условие:

DECLARE @xml XML=
N'<root>
  <ParentGroup>
    <ChildGroup Id="1">
      <Child Id="1">
        <Color Value="Red" />
        <Size Value="L" />
      </Child>
      <Child Id="2">
        <Color Value="Blue" />
        <Size Value="S" />
      </Child>
    </ChildGroup>
    <ChildGroup Id="2">
      <Child Id="5">
        <Color Value="Blue" />
        <Size Value="L" />
      </Child>
      <Child Id="9">
        <Color Value="Red" />
        <Size Value="S" />
      </Child>
    </ChildGroup>
  </ParentGroup>
</root>';

-- Запрос будет искать <Child>, где атрибут Value в <Size> равен "S", и удалять их <Color>

SET @xml.modify('delete /root/ParentGroup/ChildGroup/Child[Size/@Value="S"]/Color');

SELECT @xml;

если вам нужно ввести "S" в качестве переменной, вы можете использовать sql:variable()

DECLARE @SearchFor VARCHAR(10)='S';
SET @xml.modify('delete /root/ParentGroup/ChildGroup/Child[Size/@Value=sql:variable("@SearchFor")]/Color');
person Shnugo    schedule 08.05.2018