简体   繁体   中英

How do I set the xmlns attribute on the root element in the generated XML by using T-SQL's xml data type method: query?

I've created a simplified version of my problem:

DECLARE @X XML = 
'<Root xmlns="TestNS" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Test>
        <Id>1</Id>
        <InnerCollection>
            <InnerItem>
                <Value>1</Value>
            </InnerItem>
            <InnerItem>
                <Value>2</Value>
            </InnerItem>
            <InnerItem>
                <Value>3</Value>
            </InnerItem>
        </InnerCollection>
    </Test>
    <Test>
        <Id>2</Id>
        <InnerCollection>
            <InnerItem>
                <Value>5</Value>
            </InnerItem>
            <InnerItem>
                <Value>6</Value>
            </InnerItem>
            <InnerItem>
                <Value>7</Value>
            </InnerItem>
        </InnerCollection>
    </Test>
</Root>'

I'm trying to write a query that takes each <Test> element and breaks it into a row. On each row I want to select the Id and the InnerCollection as XML. I want to create this InnerCollection XML for the first row (Id:1):

<InnerCollection xmlns="Reed.Api" xmlnsi="http//www.w3.org/2001/XMLSchema-instance">
  <InnerItem>
    <Value>1</Value>
  </InnerItem>
  <InnerItem>
    <Value>2</Value>
  </InnerItem>
  <InnerItem>
    <Value>3</Value>
  </InnerItem>
</InnerCollection>

I tried doing that with this query but it puts a namespace I don't want on the elements:

;WITH XMLNAMESPACES
(
    DEFAULT 'TestNS'
    , 'http://www.w3.org/2001/XMLSchema-instance' AS i
)
SELECT 
    X.value('Id[1]', 'INT') Id
    -- Creates a p1 namespace that I don't want.
    , X.query('InnerCollection') InnerCollection
FROM @X.nodes('//Test') AS T(X)

My Google-fu isn't very strong today, but I imagine it doesn't make it any easier that the darn function is called query. I'm open to using other methods to create that XML value other than the query method.

I could use this method:

;WITH XMLNAMESPACES
(
    DEFAULT 'TestNS'
    , 'http://www.w3.org/2001/XMLSchema-instance' AS i
)
SELECT 
    X.value('Id[1]', 'INT') Id
    ,CAST(
        (SELECT 
            InnerNodes.Node.value('Value[1]', 'INT') AS 'Value'
        FROM X.nodes('./InnerCollection[1]//InnerItem') AS InnerNodes(Node) 
        FOR XML PATH('InnerItem'), ROOT('InnerCollection')
        ) AS XML) AS InnerCollection
FROM @X.nodes('//Test') AS T(X)

But that involves calling nodes on it to break it out into something selectable, and then selecting it back into XML using FOR XML... when it was XML to begin with. This seems like a inefficient method of doing this, so I'm hoping someone here will have a better idea.

This is how to do the SELECT using the query method to create the XML on each row that my question was looking for:

;WITH XMLNAMESPACES
(
    'http://www.w3.org/2001/XMLSchema-instance' AS i
    , DEFAULT 'TestNS'
)
SELECT
    Test.Row.value('Id[1]', 'INT') Id
    , Test.Row.query('<InnerCollection xmlns="TestNS" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">{InnerCollection}</InnerCollection>')
FROM @X.nodes('/Root/Test') AS Test(Row)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM