0

Please could someone give some guidance on the most efficient way to extract some values from an XML column? I've tried using substring and charindex within a case statement but this gets really messy and isn't the best performer. I would have thought that there is an XML function which would work better but struggling to find any examples online that use XML anything like this;

<pro:Import xmlns:pro="http://thenamespace/">
<pro:Control DatabaseName="varchar" UserName="varchar" Password="varchar" Company="varchar" Version="varchar" ErrorHandlingMode="varchar" />
<pro:Invoice RegisterInvoiceEvenIfParentOrdersAreInvalid="Bool" Tray="Varchar" Template="varchar" Supplier="varchar" SupplierInvoiceNumber="int" InvoiceDate="datetime" GrossValue="decimal" TaxValue="decimal" ImageReference="uniqueidentifier">
    <pro:References>
        <pro:Reference Code="varchar" Value="datetime" />
        <pro:Reference Code="varchar" Value="varchar" />
    </pro:References>
    <pro:ParentOrders>
        <pro:ParentOrder OrderNumber="varchar" />
    </pro:ParentOrders>
    <pro:TaxDetails>
        <pro:Tax Band="varchar" Code="varchar" GrossValue="decimal" TaxValue="decimal" />
    </pro:TaxDetails>
    <pro:Comments>
        <pro:Comment>varchar</pro:Comment>
    </pro:Comments>
</pro:Invoice>

The values I want to extract will vary, as will the XML. This is one example but there may be times when the values i want to extract for some XML are not present in others.

Example:

There might always be a Supplier="xxxx" but not a SupplierInvoiceNumber="xxxx" and its position will vary.

For arguments sake though, lets say for this exercise i just want to pull out

Supplier="varchar" & SupplierInvoiceNumber="int"

Thanks all :)

~D

1 Answer 1

1

Your XML misses the closing final tag...

I've tried using substring and charindex within a case statement but this gets really messy and isn't the best performer.

It is a very bad idea to try to read from XML on string level...

Try it like this:

DECLARE @xml XML=
N'<pro:Import xmlns:pro="http://thenamespace/">
  <pro:Control DatabaseName="varchar" UserName="varchar" Password="varchar" Company="varchar" Version="varchar" ErrorHandlingMode="varchar" />
  <pro:Invoice RegisterInvoiceEvenIfParentOrdersAreInvalid="Bool" Tray="Varchar" Template="varchar" Supplier="varchar" SupplierInvoiceNumber="int" InvoiceDate="datetime" GrossValue="decimal" TaxValue="decimal" ImageReference="uniqueidentifier">
    <pro:References>
      <pro:Reference Code="varchar" Value="datetime" />
      <pro:Reference Code="varchar" Value="varchar" />
    </pro:References>
    <pro:ParentOrders>
      <pro:ParentOrder OrderNumber="varchar" />
    </pro:ParentOrders>
    <pro:TaxDetails>
      <pro:Tax Band="varchar" Code="varchar" GrossValue="decimal" TaxValue="decimal" />
    </pro:TaxDetails>
    <pro:Comments>
      <pro:Comment>varchar</pro:Comment>
    </pro:Comments>
  </pro:Invoice>
</pro:Import>';

--Clean

WITH XMLNAMESPACES(DEFAULT 'http://thenamespace/')
SELECT @xml.value('(/Import/Invoice/@Supplier)[1]','nvarchar(max)') AS Supplier
      ,@xml.value('(/Import/Invoice/@SupplierInvoiceNumber)[1]','nvarchar(max)') AS SupplierInvoiceNumber

--Lazy

SELECT @xml.value('(//@Supplier)[1]','nvarchar(max)') AS Supplier
      ,@xml.value('(//@SupplierInvoiceNumber)[1]','nvarchar(max)') AS SupplierInvoiceNumber
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect thanks! I had tried with xml.Value but i was trying to read it like this, based on something i found online, (/ns:Import/ns:Invoice)[1]', 'varchar(max)') as 'Supplier' and this returned the comments instead. Thanks for the really speedy response!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.