私はOPENXML
を利用した名前空間を列挙するため、むしろ古い方法があることが、this threadから学んだ:
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