4

I have following XML code snippet and I am trying to read it in tabular format using SQL Server.

declare @ProductXML varchar(max);
set @ProductXML = '<hashtable>   <entry>
    <string>host</string>
    <string-array>
      <string>csdfs</string>
    </string-array>
  </entry>
 <entry> <string>dom</string><map-array>
      <map>
        <entry>
          <string>thirdlevelentrey</string>
          <vector>
            <string>1in</string>
            <string>2in</string>
            <string>3in</string>
            <string>4in</string>
            <string>5in</string>
          </vector>
        </entry>
      </map>
    </map-array></entry>
</hashtable>'

DECLARE @xml xml

SELECT @xml = CAST(CAST(@ProductXML AS VARBINARY(MAX)) AS XML)

SELECT  
    x.Rec.query('./string').value('.', 'nvarchar(50)') AS 'Product Name', 
    x.Rec.query('./vector/string').value('.', 'nvarchar(50)') AS 'Product TLDs' 
FROM 
    @xml.nodes('/hashtable/entry/map-array/map/entry') AS x(Rec)

I am facing the issue with second column Product TLDs. In under the vector multiple rows value merged in single text. I want them with separator or delimited text so I could recognize them later when I use.

If someone can help me to place a separator or deliminator such as 1in|2in|3in and so on...

or can it be possible to in a child table considering thirdlevelentry as a table.

1
  • 1
    Mysql has nothing to do with ms sql server. Commented Dec 9, 2017 at 21:46

2 Answers 2

5

You could use

SUBSTRING(
x.Rec.query('for $string in ./vector/string/text()  
            return  concat("|", $string)
').value('.', 'nvarchar(50)'),
2,50) AS [Product TLDs]

This returns

1in |2in |3in |4in |5in

So injects some additional spaces. If the values you are concatenating won't contain any spaces you could use

REPLACE(
x.Rec.query('for $string in ./vector/string/text()  
            return string($string)
').value('.', 'nvarchar(50)'),
' ','|') AS [Product TLDs] 

Which returns

1in|2in|3in|4in|5in
Sign up to request clarification or add additional context in comments.

Comments

2

If your values within <vector><string> don't contain blanks there's a very easy solution:

SELECT  
    x.Rec.query('./string').value('.', 'nvarchar(50)') AS 'Product Name', 
    x.Rec.query('data(./vector/string)').value('.', 'nvarchar(50)') AS 'Product TLDs' 
FROM 
    @xml.nodes('/hashtable/entry/map-array/map/entry') AS x(Rec);

The XQuery function .data() will return all content with a blank as separator. I have no idea, why they did not add a second parameter to sepcify the separator...

If your strings contain blanks Martin Smith's FLWOR approach is great!

3 Comments

And they can always use REPLACE to convert the spaces to pipes if needed
@MartinSmith, Sure, like in your second suggestion... Do you have an idea, why there's no chance to specify the separator?
No - I'm not well versed in the intricacies of Xquery. Shame SQL Server doesn't support string-join though.

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.