For xml path format question

  • Hey, as some of you guys know im building a mailing system, and yesterday i learned about the wonderful for xml path operator.

    I got it to work, but im having a minor format problem. The for xml path operator converts characters like < and > to & lt and & gt.

    This screws up the html format of the email... Insted of interpreting the html <img>, it just writes it out as plain text.

    Is there any way to convert them back to <>?

    Here's a sample

    SELECT '<img src="http://simple-image-reducer.org.ua/static/img/simple-image-reducer-big.png" />' for xml path('td')

    Ty

  • Why are you using an XML in the select with for xml clause? The for xml clause is meant to be used when you take a tabular data and want to convert it to XML.

    The XML that you are getting is because as far as SQL Server knows, it takes a string and converts it to XML. Strings in XML can’t contain characters that mark the beginning or end of an element. For example this is not a valid XML

    <math>5<8</math>

    The sign < is part of the string, but it confuses any XML reader application to think that an element was just opened. In order to make it a valid XML we need to modify it and use the escape char & l t ; (without the spaces. I've added the spaces because without it you don't see the escape charatar) instead of the < sign

    The same thing happened to your XML. SQL Server treated your XML as string so it had to replace the signs < and > with there escape characters. If you don’t want that to happen, you have to let SQL Server know that it should treat it as XML and not as string. You can do it with the CAST function. Here is an example:

    SELECT cast('<img src="http://simple-image-reducer.org.ua/static/img/simple-image-reducer-big.png" />' as XML) for xml path('td')

    Adi

    --------------------------------------------------------------
    To know how to ask questions and increase the chances of getting asnwers:
    http://www.sqlservercentral.com/articles/Best+Practices/61537/

    For better answers on performance questions, click on the following...
    http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • Adi Cohn-120898 (11/24/2011)


    Why are you using an XML in the select with for xml clause?

    I used it to demonstrate the problem. The actual code looks like this:

    declare @clikesstring varchar(MAX)

    SELECT DISTINCT [databases].dbo.users.id, +'<table>'+

    STUFF((SELECT +'<img href="http://google.com/'+cast(companies.dbo.companies.id as varchar(50))+'_thumb.jpg>' AS

    , companies.dbo.companies.company AS

    FROM [databases].dbo.users INNER JOIN

    companies.dbo.likes ON [databases].dbo.users.id = companies.dbo.likes.userid INNER JOIN

    companies.dbo.companies ON companies.dbo.likes.companyid = companies.dbo.companies.id WHERE users.id = 1

    ORDER BY users.id for xml path('tr')),1,1,'<')+'</table>' AS clikes

    INTO #temp1

    FROM [databases].dbo.users INNER JOIN

    companies.dbo.likes ON [databases].dbo.users.id = companies.dbo.likes.userid INNER JOIN

    companies.dbo.companies ON companies.dbo.likes.companyid = companies.dbo.companies.id WHERE users.id = 1

    ORDER BY users.id

    SELECT @clikesstring=clikes FROM #temp1

    print REPLACE(REPLACE(@clikesstring, N'<', N'<'), N'>', N'>')

    DROP TABLE #temp1

    I used replace function but it doesn't feel as robust as your solution.

    print REPLACE(REPLACE(@clikesstring, N'<', N'<'), N'>', N'>')

    I tryed the cast on the varchar but got error: XML parsing: line 1, character 77, unexpected end of input

    SELECT +cast('<img href="http://google.com/'+cast(companies.dbo.companies.id as varchar(50))+'_thumb.jpg>' as xml) AS

    ,

    And while replacing <> to & l t ; without spaces, i still got wrong output... (& l t ; instead of the less sign)

    Any ideas?

  • BEGIN TRAN

    CREATE TABLE companies (id INT)

    INSERT INTO companies

    SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3

    SELECT CAST('<img href="http://google.com/' + CAST(id AS VARCHAR(50)) + '_thumb.jpg" />' AS XML) AS

    FROM companies

    ROLLBACK

    Returns

    td

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    <img href="http://google.com/1_thumb.jpg" />

    <img href="http://google.com/2_thumb.jpg" />

    <img href="http://google.com/3_thumb.jpg" />


    --edit--

    BEGIN TRAN

    CREATE TABLE companies (id INT)

    INSERT INTO companies

    SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3

    DECLARE @sql AS VARCHAR(MAX)

    SELECT @sql = COALESCE(@SQL,'') +

    '<img href="http://google.com/' + CAST(id AS VARCHAR(50)) + '_thumb.jpg" />'

    FROM companies

    SELECT @sql = '<table>'+@SQL+'</table>'

    SELECT CAST(@SQL AS XML)

    ROLLBACK

    Returns

    <table>

    <img href="http://google.com/1_thumb.jpg" />

    <img href="http://google.com/2_thumb.jpg" />

    <img href="http://google.com/3_thumb.jpg" />

    </table>


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • Oh, ty so much, it actually worked after all. I realize now that i've missed a couple of html errors in my prototype version! Which XML noticed and threw up errors.

Viewing 5 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic. Login to reply