我從this thread中瞭解到,還有一個比較舊的方式來枚舉命名空間利用OPENXML
:我不清楚如何優雅,這是
DECLARE @SomeXML xml = N'<ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema-instance"><blubb xmlns:xsiu="http://www.w3.org/2001/XMLSchema-instance"><blah xsi:nil="true"/></blubb></ROOT>';
DECLARE @hDoc int;
EXEC sys.sp_xml_preparedocument
@hDoc OUTPUT,
@SomeXML;
IF EXISTS (SELECT namespace = NULLIF(XmlnsAttribute.localname, 'xmlns'),
namespace_uri = XmlnsValue.text
FROM OPENXML(@hDoc, '//*') XmlnsAttribute
INNER JOIN OPENXML(@hDoc, '//*') XmlnsValue ON XmlnsValue.parentid = XmlnsAttribute.id
WHERE XmlnsAttribute.prefix = 'xmlns'
AND XmlnsValue.nodetype = 3 /*text*/
AND CAST(XmlnsValue.text AS nvarchar(MAX)) = N'http://www.w3.org/2001/XMLSchema-instance')
PRINT 'Has http://www.w3.org/2001/XMLSchema-instance namespace';
ELSE
PRINT 'Does not have http://www.w3.org/2001/XMLSchema-instance namespace';
EXEC sys.sp_xml_removedocument
@hDoc;
,爲text
列是ntext
類型,並sys.sp_xml_preparedocument
來電和sys.sp_xml_removedocument
的意思是,當您將其包含在其他查詢中時,您需要多加註意。可能最糟糕的缺點是,你需要做這個RBAR。
仍然這是一個解決方案,沒有鑄造xml
到varchar
,所以它應該很難欺騙。
列出所有命名空間:
DECLARE @SomeXML xml = N'<ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema-instance"><blubb xmlns:xsiu="http://www.w3.org/2001/XMLSchema-instance"><blah xsi:nil="true"/></blubb></ROOT>';
DECLARE @hDoc int;
EXEC sys.sp_xml_preparedocument
@hDoc OUTPUT,
@SomeXML;
-- All registered namespaces
WITH XmlNodes
AS (SELECT OX.id,
OX.parentid,
OX.nodetype,
OX.localname,
OX.prefix,
OX.text
FROM OPENXML(@hDoc, '//*') OX)
SELECT namespace = NULLIF(XmlnsAttribute.localname, 'xmlns'),
namespace_uri = XmlnsValue.text
FROM XmlNodes XmlnsAttribute
INNER JOIN XmlNodes XmlnsValue ON XmlnsValue.parentid = XmlnsAttribute.id
WHERE XmlnsAttribute.prefix = 'xmlns'
AND XmlnsValue.nodetype = 3
/*text*/;
-- All registered namespaces with scope
WITH XmlNodes
AS (SELECT OX.id,
OX.parentid,
OX.nodetype,
OX.localname,
OX.prefix,
OX.text
FROM OPENXML(@hDoc, '//*') OX),
XmlNodesWithPath
AS (SELECT XN.id,
path = CAST(N'/' + ISNULL(XN.prefix + N':', N'') + XN.localname AS nvarchar(MAX))
FROM XmlNodes XN
WHERE XN.parentid IS NULL
UNION ALL
SELECT XN.id,
path = XNWP.path + N'/' + ISNULL(XN.prefix + N':', N'') + XN.localname
FROM XmlNodesWithPath XNWP
INNER JOIN XmlNodes XN ON XN.parentid = XNWP.id
AND XN.nodetype = 1)
SELECT scope = Scope.path,
namespace = NULLIF(XmlnsAttribute.localname, 'xmlns'),
namespace_uri = XmlnsValue.text
FROM XmlNodesWithPath Scope
INNER JOIN XmlNodes XmlnsAttribute ON XmlnsAttribute.parentid = Scope.id
INNER JOIN XmlNodes XmlnsValue ON XmlnsValue.parentid = XmlnsAttribute.id
WHERE XmlnsAttribute.prefix = 'xmlns'
AND XmlnsValue.nodetype = 3
/*text*/;
EXEC sys.sp_xml_removedocument
@hDoc;
而且因爲它感覺不對我問SO上,希望有另一種方式:d – TheConstructor
我終於找到了利用XML的功能的解決方案。仍然不完全開心。 – TheConstructor