使用SQL Server中的OPENXML解析带有内联架构的XML文件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用SQL Server中的OPENXML解析带有内联架构的XML文件相关的知识,希望对你有一定的参考价值。
我试图从XML文件中提取数据并使用SQL Server中的OPENXML存储到SQL表中。但是,查询什么都不返回。
CML日期
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/>
<xsd:element name="ogridroles">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ogrid_cde" type="sqltypes:int" nillable="1"/>
<xsd:element name="role" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:char" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="1"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>28</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>75</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>93</ogrid_cde>
<role>O</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>135</ogrid_cde>
<role>O</role>
</ogridroles>
</root>
SQL查询
DECLARE @xmlStr xml;
DECLARE @idoc INT
SELECT @xmlStr = BulkColumn FROM OPENROWSET(
BULK 'D:ogridroles.xml',
SINGLE_BLOB) AS DATA;
EXEC sp_xml_preparedocument @idoc OUTPUT, @xmlStr;
SELECT *
FROM OPENXML (@idoc, '/root/ogridroles',2)
WITH (
ogrid_cde int 'ogrid_cde',
role varchar(1) 'role')
EXEC sp_xml_removedocument @idoc
我想提取元素的所有行值
ogrid_cde 角色
答案
通过FROM OPENXML
的方法(连同准备和删除文件的程序)已过时,不应再使用。
更好的是native methods of the XML-type。试试这个:
你的XML
DECLARE @xml XML=
N'<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsd:schema xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="ogridroles">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ogrid_cde" type="sqltypes:int" nillable="1" />
<xsd:element name="role" nillable="1">
<xsd:simpleType>
<xsd:restriction base="sqltypes:char" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="1" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>28</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>75</ogrid_cde>
<role>T</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>93</ogrid_cde>
<role>O</role>
</ogridroles>
<ogridroles xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1">
<ogrid_cde>135</ogrid_cde>
<role>O</role>
</ogridroles>
</root>';
- 查询
WITH XMLNAMESPACES(DEFAULT 'urn:schemas-microsoft-com:sql:SqlRowSet1')
SELECT OgrRol.value('(ogrid_cde/text())[1]','int') AS ogrid_cde
,OgrRol.value('(role/text())[1]','nvarchar(10)') AS [role]
FROM @xml.nodes('/*:root/ogridroles') A(ogrRol);
结果
ogrid_cde role
28 T
75 T
93 O
135 O
简短说明
你可以在这里忽略XML模式。这对于检查数据完整性和有效性非常有用。但假设数据是正确的,我们可以阅读它。
有一个(重复定义的)默认命名空间。但是 - 这很重要! - 元素<root>
本身并不存在于此命名空间中!
轻松一点,我刚刚使用命名空间通配符来使用*:root
来处理这个元素。一般来说,最好避免使用通配符,但在这种情况下,这似乎是可以接受的。
我们使用.nodes()
来获取所有<ogridroles>
元素的派生表。然后我们使用.value()
来读取代码和角色元素的text()
节点。
希望这有帮助,快乐编码!
另一答案
我不太喜欢模式并使用另一种方法来解码XML:
DECLARE @x XML = 'bla bla bla'
DECLARE @idoc INT
EXEC sp_xml_preparedocument @idoc OUTPUT ,@x
SELECT * INTO #t
FROM OPENXML (@idoc, '/',2)
EXEC sp_xml_removedocument @idoc
SELECT [ogrid_cde] = t3.text, [role] = t4.text
FROM #t as t1
INNER JOIN #t as t2 ON t1.parentid = t2.parentid
INNER JOIN #t as t3 ON t1.id = t3.parentid
INNER JOIN #t as t4 ON t2.id = t4.parentid
WHERE t1.localname = 'ogrid_cde' and t2.localname = 'role'
以上是关于使用SQL Server中的OPENXML解析带有内联架构的XML文件的主要内容,如果未能解决你的问题,请参考以下文章
sql OPENXML()在SQL Server中粉碎XML的方法