Search code examples
xmlt-sqlsql-server-2014

How to modify XML node that contains a specific child node value?


I have a table with an XML column. How can I add another node inside a node that contains a child node with a specific value? For example I'd like to copy foo/bar/e/f node from barId 6699 to barId 66989. I only find examples where you select node based on an attribute value. I need to filter by child node value instead.

<foo>
    <bar>
        <barId>66988</barId>
        <name>baz 3</name>
    </bar>
    <bar>
        <barId>66989</barId>
        <name>b </name>
        <e>
            <g>
                <h>
                    <l>-</l>
                    <m>k</m>
                </h>
                <h>
                    <l>p  v</l>
                    <m>k</m>
                </h>
            </g>
        </e>
    </bar>
    <bar>
        <barId>6699</barId>
        <name>n 4 c</name>
        <e>
            <f>
                <h>
                    <i>k</i>
                    <j>9.3</j>
                </h>
            </f>
        </e>
    </bar>
</foo>

Solution

  • Try this:

    DECLARE @value XML = '<foo><bar><barId>66988</barId><name>baz 3</name></bar><bar><barId>66989</barId><name>b </name><e><g><h><l>-</l><m>k</m></h><h><l>p  v</l><m>k</m></h></g></e></bar><bar><barId>6699</barId><name>n 4 c</name><e><f><h><i>k</i><j>9.3</j></h></f></e></bar></foo>';
    
    DECLARE @SourceID INT = 6699;
    DECLARE @DestinationID INT = 66989;
    
    DECLARE @temp XML;
    
    SELECT @temp = T.c.query('.')
    FROM @value.nodes('/foo/bar[barId = sql:variable("@SourceID")]/e/f') T(c);
    
    SELECT @temp;
    
    SET @value.modify('insert sql:variable("@temp") as last into (/foo/bar[barId =sql:variable("@DestinationID")]/e)[1]')
    
    SELECT @value;
    

    It will give you this:

    <foo>
      <bar>
        <barId>66988</barId>
        <name>baz 3</name>
      </bar>
      <bar>
        <barId>66989</barId>
        <name>b </name>
        <e>
          <g>
            <h>
              <l>-</l>
              <m>k</m>
            </h>
            <h>
              <l>p  v</l>
              <m>k</m>
            </h>
          </g>
          <f>
            <h>
              <i>k</i>
              <j>9.3</j>
            </h>
          </f>
        </e>
      </bar>
      <bar>
        <barId>6699</barId>
        <name>n 4 c</name>
        <e>
          <f>
            <h>
              <i>k</i>
              <j>9.3</j>
            </h>
          </f>
        </e>
      </bar>
    </foo>