Tejas
Tejas

Reputation: 97

Get value by passing dynamic node name of XML

I want get value of node by passing node name dynamically.

I am using this xml:

DECLARE @xml AS XML = '<AuditMsg>
  <SourceDb>TestDatabase</SourceDb>
  <SourceTable>Person</SourceTable>
  <PKFieldName>ID</PKFieldName>
  <UserId>sa</UserId>
  <DMLType>I</DMLType>
  <OldData />
  <ChangedData>
    <t xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ID>4</ID>
      <FirstName>name 4</FirstName>
      <LastName>surname 4</LastName>
      <DateOfBirth>444444</DateOfBirth>
    </t>
  </ChangedData>
</AuditMsg>'
INSERT INTO @changed
    SELECT
        changed.col.value('local-name(.)', 'VARCHAR(100)') AS Name,
        changed.col.value('.[1]', 'VARCHAR(14)') AS Value,
        ROW_NUMBER() OVER (PARTITION BY changed.col.value('local-name(.)', 'VARCHAR(100)') ORDER BY (SELECT 0)) AS RecordId,
        changed.col.value('(/t/ID)[1]', 'INT') AS ApplicationID
    FROM 
        @ChangedData CD
    CROSS APPLY 
        CD.ChangedData.nodes('/t/*') AS changed(col)

At the 6th line I am passing node name statically as ID. I want to pass that node name dynamically I am trying to do like

DECLARE @Attribute varchar(100) = 'ID'

INSERT INTO @changed
    SELECT
        changed.col.value('local-name(.)', 'VARCHAR(100)') AS Name,
        changed.col.value('.[1]', 'VARCHAR(14)') AS Value,
        ROW_NUMBER() OVER (PARTITION BY changed.col.value('local-name(.)', 'VARCHAR(100)') ORDER BY (SELECT 0)) AS RecordId,
        changed.col.value('(/t/' + @Attribute +')[1]', 'INT') AS ApplicationID
    FROM 
        @ChangedData CD
    CROSS APPLY 
        CD.ChangedData.nodes('/t/*') AS changed(col)

By passing node name dynamically I am getting this error (The argument 1 of the XML data type method "value" must be a string literal)

How can I achieve this?

Upvotes: 1

Views: 1490

Answers (1)

Gottfried Lesigang
Gottfried Lesigang

Reputation: 67311

Are you looking for something along this?

DECLARE @xml AS XML = 
'<AuditMsg>
  <SourceDb>TestDatabase</SourceDb>
  <SourceTable>Person</SourceTable>
  <PKFieldName>ID</PKFieldName>
  <UserId>sa</UserId>
  <DMLType>I</DMLType>
  <OldData />
  <ChangedData>
    <t xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ID>4</ID>
      <FirstName>name 4</FirstName>
      <LastName>surname 4</LastName>
      <DateOfBirth>444444</DateOfBirth>
    </t>
  </ChangedData>
</AuditMsg>'

--your externally defined variable

DECLARE @Attribute varchar(100) = 'ID'

--The query

SELECT @xml.value('(/AuditMsg
                    /ChangedData
                    /t
                    /*[local-name()=sql:variable("@Attribute")]
                    /text())[1]','nvarchar(max)');

The XPath will dive down into <t> and find the element, where the element's name equals your parameter passed in via sql:variable(). Within this element we pick the text() node.

Upvotes: 2

Related Questions