3
votes

I would like to read the xsi:type attribute from the "current" node in a SELECT statement. My XML looks like this:

 <ns2:data xmlns:ns2="http://mynamespace">
  <OrderLineItems>
    <OrderLineItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:DeactivationLineItem" id="1">
      <Product>
        <Id>5300</Id>
        <Description>DUMMY</Description>
        <Domain>ddd</Domain>
      </Product>
      <Quantity>1</Quantity>
    </OrderLineItem>
    <OrderLineItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:ActivationLineItem" id="4">
      <Product>
        <Id>5340</Id>
        <Description>DUMMY</Description>
        <Domain>aaa</Domain>
      </Product>
      <Quantity>1</Quantity>
    </OrderLineItem>
    <OrderLineItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:DeactivationLineItem" id="12">
      <Product>
        <Id>53200</Id>
        <Description>DUMMY</Description>
        <Domain>ccc</Domain>
      </Product>
      <Quantity>21</Quantity>
    </OrderLineItem>
  </OrderLineItems>
</ns2:data>

My select statement looks as follows:

;WITH XMLNAMESPACES('http://mynamespace' AS ns)
SELECT
,OrderLineItemID                = ref.value('@id', 'int')
,OrderLineItemParentID          = ref.value('@parentId', 'int')
,ProductID                      = NULLIF(ref.query('Product/Id').value('.', 'varchar(255)'),'')
,ProductDescription             = NULLIF(ref.query('Product/Description').value('.', 'varchar(255)'),'')
,ProductDomain                  = NULLIF(ref.query('Product/Domain').value('.', 'varchar(255)'),'')
,ProductAdditionalInfo          = NULLIF(ref.query('Product/AdditionalInfo').value('.', 'varchar(255)'),'')
,Quantity                       = ref.query('Quantity').value('.', 'int')

,LineItemType                   = ref.value('@xsi:type','varchar(max)')                 

FROM tTEMP_XMLTABLE
CROSS APPLY xmlFile.nodes('/ns:data/OrderLineItems/OrderLineItem') R(ref) 

My problem is the line LineItemType as it throws an error: The XQuery syntax '@{http://www.w3.org/2001/XMLSchema-instance}:type' is not supported

It is strange, because I am able to read a single type if I don't use the CROSS APPLY:

WITH  XMLNAMESPACES ('http://mynamespace' as p)
SELECT CAST(xmlFile as XML).value('(/p:data/OrderLineItems/OrderLineItem/@xsi:type)[1]','nvarchar(max)')
from tTEMP_XMLTABLE;

The second statement works on SQL Server 2005. Is there a possibility to read the xsi:type attribute when using cross apply?

Thanks for the help

1
[This article][1] might be of some help... [1]: stackoverflow.com/questions/2477237/… - mwigdahl
Thanks, but this describes the second sql statement i've posted. I need to read ALL Types in a CrossApply - merror
Interesting. What type is "xmlFile"? I was able to get this to work for your xml if I stored it in an xml-typed variable. - mwigdahl
"xmlFile" is a column Name in the tTEMP_XMLTABLE, Datatype is XML (with an XSD schema behind it) - merror
Ah, that may be the issue then. See below for how I was able to get it to work by putting it into an untyped xml field in a table (in this case, a table variable). Not sure if that's possible for you, but it does work. - mwigdahl

1 Answers

1
votes

This worked for me in SQL Server 2008 SP1 (you didn't specify version, so I'm not sure if that is what you have or not). Not sure if it's possible for you to get your xml or a copy of your xml into an untyped xml field like I have here, but that might help you get around the schema-bound issue from the link I gave you above.

DECLARE @tmp_xml TABLE (id int identity, data xml)

INSERT INTO @tmp_xml (data)
VALUES ('<ns2:data xmlns:ns2="http://mynamespace">
  <OrderLineItems>
    <OrderLineItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:DeactivationLineItem" id="1">
      <Product>
        <Id>5300</Id>
        <Description>DUMMY</Description>
        <Domain>ddd</Domain>
      </Product>
      <Quantity>1</Quantity>
    </OrderLineItem>
    <OrderLineItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:ActivationLineItem" id="4">
      <Product>
        <Id>5340</Id>
        <Description>DUMMY</Description>
        <Domain>aaa</Domain>
      </Product>
      <Quantity>1</Quantity>
    </OrderLineItem>
    <OrderLineItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:DeactivationLineItem" id="12">
      <Product>
        <Id>53200</Id>
        <Description>DUMMY</Description>
        <Domain>ccc</Domain>
      </Product>
      <Quantity>21</Quantity>
    </OrderLineItem>
  </OrderLineItems>
</ns2:data>')

;WITH XMLNAMESPACES('http://mynamespace' AS ns)
SELECT
OrderLineItemID                = ref.value('@id', 'int')
,OrderLineItemParentID          = ref.value('@parentId', 'int')
,ProductID                      = NULLIF(ref.query('Product/Id').value('.', 'varchar(255)'),'')
,ProductDescription             = NULLIF(ref.query('Product/Description').value('.', 'varchar(255)'),'')
,ProductDomain                  = NULLIF(ref.query('Product/Domain').value('.', 'varchar(255)'),'')
,ProductAdditionalInfo          = NULLIF(ref.query('Product/AdditionalInfo').value('.', 'varchar(255)'),'')
,Quantity                       = ref.query('Quantity').value('.', 'int')

,LineItemType                   = ref.value('@xsi:type','varchar(max)')                 

FROM @tmp_xml t
    CROSS APPLY data.nodes('/ns:data/OrderLineItems/OrderLineItem') R(ref)