如何从数据库字段中解析 XML?

How can I parse XML from database field?

与以下 XML.

合作
<TEMPLATE>
<TEMPLATE_FIELD prompt="TEST_ONE" data_type="8" tag="TEST_ONE" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
<TEMPLATE_FIELD prompt="TEST_TWO" data_type="8" tag="TEST_TWO" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
<TEMPLATE_FIELD prompt="TEST_THREE" data_type="8" tag="TEST_THREE" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />

我正在尝试获取以下内容 - 或类似的内容,以便我可以有效地阅读这些字段。

我试过其他几个问题,发现这个问题的第三个答案很有希望 -- 因为我希望能够在 SQL 中解析而不是使用外部语言或者创建一个文件。如果创建文件更容易,请随时分享。我已经尝试了下面代码的几种变体,但得到的不是“空白”就是 NULL。

declare @xml as xml
set @xml = (SELECT xml_field from fooXMLtable)

select @xml

;with cte as (    
  select @xml xmlstring
)
SELECT 
xmlstring.value('(/TEMPLATE//TEMPLATE_FIELD/prompt/node())[3]','VARCHAR(max)')
as prompt

首先nodes() to get the TEMPLATE_FIELD elements a a table and then select from that table using value()从属性中获取值。

SELECT tf.value('@prompt', 'varchar(MAX)') prompt,
       tf.value('@data_type', 'integer') data_type,
       ...
       FROM @xml.nodes('/TEMPLATE/TEMPLATE_FIELD') tf
                                                   (tf);

请尝试以下解决方案。

这是一个最小的可重现示例。您可以将它原样复制到 SSMS,运行 它,并探索它的作用。

它正在使用 XQuery 及其方法:.nodes().value()

无需使用临时 T-SQL 变量 @xml 作为 XML 数据占位符。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata) VALUES
(N'<TEMPLATE>
    <TEMPLATE_FIELD prompt="TEST_ONE" data_type="8" tag="TEST_ONE" required="0"
                    is_radio="0" default_value=""
                    SQL="SELECT * FROM DBO.SOME_NEW_TEST"/>
    <TEMPLATE_FIELD prompt="TEST_TWO" data_type="8" tag="TEST_TWO" required="0"
                    is_radio="0" default_value=""
                    SQL="SELECT * FROM DBO.SOME_NEW_TEST"/>
    <TEMPLATE_FIELD prompt="TEST_THREE" data_type="8" tag="TEST_THREE"
                    required="0" is_radio="0" default_value=""
                    SQL="SELECT * FROM DBO.SOME_NEW_TEST"/>
</TEMPLATE>');
-- DDL and sample data population, end

SELECT ID 
    , c.value('@prompt', 'VARCHAR(30)') AS prompt
    , c.value('@data_type', 'INT') AS data_type
    , c.value('@tag', 'VARCHAR(30)') AS tag
    , c.value('@required', 'INT') AS [required]
    , c.value('@is_radio', 'INT') AS [is_radio]
    , c.value('@default_value', 'VARCHAR(30)') AS default_value
    , c.value('@SQL', 'VARCHAR(MAX)') AS [SQL]
FROM @tbl CROSS APPLY xmldata.nodes('/TEMPLATE/TEMPLATE_FIELD') AS t(c);

输出

+----+------------+-----------+------------+----------+----------+---------------+---------------------------------+
| ID |   prompt   | data_type |    tag     | required | is_radio | default_value |               SQL               |
+----+------------+-----------+------------+----------+----------+---------------+---------------------------------+
|  1 | TEST_ONE   |         8 | TEST_ONE   |        0 |        0 |               | SELECT * FROM DBO.SOME_NEW_TEST |
|  1 | TEST_TWO   |         8 | TEST_TWO   |        0 |        0 |               | SELECT * FROM DBO.SOME_NEW_TEST |
|  1 | TEST_THREE |         8 | TEST_THREE |        0 |        0 |               | SELECT * FROM DBO.SOME_NEW_TEST |
+----+------------+-----------+------------+----------+----------+---------------+---------------------------------+

如果您使用的是 MSSQL,这应该可行:

DECLARE @xml XML = '<TEMPLATE>
<TEMPLATE_FIELD prompt="TEST_ONE" data_type="8" tag="TEST_ONE" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
<TEMPLATE_FIELD prompt="TEST_TWO" data_type="8" tag="TEST_TWO" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
<TEMPLATE_FIELD prompt="TEST_THREE" data_type="8" tag="TEST_THREE" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
</TEMPLATE>'

SELECT 
    T.C.value('./@prompt', 'nvarchar(50)') as Prompt,
    T.C.value('./@data_type', 'int') as DataType,
    T.C.value('./@tag', 'nvarchar(50)') as Tag,
    T.C.value('./@required', 'bit') as Required,
    T.C.value('./@is_radio', 'bit') as IsRadio,
    T.C.value('./@default_value', 'nvarchar(max)') as DefaultValue,
    T.C.value('./@SQL', 'nvarchar(max)') as Query
FROM   @xml.nodes('/TEMPLATE/TEMPLATE_FIELD') T(C)