Search code examples
sqlsql-serverxmlt-sqlnamespaces

How do I use following xml query without prefix?


In the following link https://msdn.microsoft.com/en-us/library/ms175178.aspx I found this quote:

"This prefix is then used in the query body instead of the namespace URI"

This makes me feel that if I do not specify prefix then I have to use uri in place of prefix. So please give me an example of using uri in place of prefix, because in above link it is not given. Only they given example of with prefix.


Solution

  • A namespace is meant to separate identically named elements. Very often XML fragments are just glued together. It is very likely, that different elements with the same name get together. By using a namespace the combination of namespace and element name is used to identify the element. But it is not important, which alias is used to point to the namespace!

    You must distinguish between the "namespace" and the given "alias".

    The following example has the element <a> in two flavours. Check this out:

    DECLARE @xml XML=
    N'<root xmlns="DefaultNS" xmlns:dns="DerivedNS">
      <a>This is default</a>
      <dns:a>This is derived</dns:a>
    </root>';
    

    --no result

    SELECT a.value(N'(text())[1]',N'nvarchar(max)')
    FROM @xml.nodes(N'/root/a') AS A(a);
    

    --wildcard-namespace: Everything

    SELECT a.value(N'(text())[1]',N'nvarchar(max)')
    FROM @xml.nodes(N'/*:root/*:a') AS A(a);
    

    --Only default namespace declared: Only default element returned

    WITH XMLNAMESPACES(DEFAULT 'DefaultNS')
    SELECT a.value(N'(text())[1]',N'nvarchar(max)')
    FROM @xml.nodes(N'/root/a') AS A(a);
    

    --.nodes() calls for the derived namespace: Only derived element returned

    WITH XMLNAMESPACES(DEFAULT 'DefaultNS'
                              ,'DerivedNS' AS xyz) --Other prefix, doesn't matter
    SELECT a.value(N'(text())[1]',N'nvarchar(max)')
    FROM @xml.nodes(N'/root/xyz:a') AS A(a); --prefix "dns" would not work, the alias is now "xyz"
    

    --Here I use random prefixes. I took "dns" as alias for the default!

    WITH XMLNAMESPACES('DefaultNS' AS dns
                      ,'DerivedNS' AS dns2) --random prefixes for the namespaces, took even dns for the wrong one!
    SELECT a.value(N'(text())[1]',N'nvarchar(max)')
    FROM @xml.nodes(N'/dns:root/dns:a') AS A(a); --prefix "dns" returns the default ns now! And you need the prefix at `root` too!
    

    --With inline declaration

    SELECT a.value(N'(text())[1]',N'nvarchar(max)')
    FROM @xml.nodes(N'declare namespace x="DefaultNS"; /x:root/x:a') AS A(a); --The alias "x" is now bound to the default namespace!