XML SQL 中的命名空间混乱
XML Namespace confusion in SQL
我有一个 XML 文件需要修改。
我可以在 SQL 中很好地加载文件,但是当我尝试读取一些节点时,我什么也没得到 returned.. 也没有错误。我做错了什么?
我的 XML 的开头是这样的:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<batch_request xmlns="http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd batchsubmission- schema.xsd">
<raise_eligibility_document>
<ed:Certificate xmlns="http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd" xmlns:ed="http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd">
<ed:Identifiers>
<ed:CertificateID>26920</ed:CertificateID>
<ed:TemplateID>ED1</ed:TemplateID>
</ed:Identifiers>
<ed:DepartureDate>2021-03-10</ed:DepartureDate>
<ed:Parties>
<ed:ConsignorID>XX345</ed:ConsignorID>
<ed:ConsigneeID>FLIGHT1</ed:ConsigneeID>
</ed:Parties>
这是我的 SQL 加载和读取此文件的语句以及我对 return 节点的尝试。
Declare @xmlFile VARCHAR(30) = 'TESTING'
if OBJECT_ID('tempdb..#XmlImportTest') is not null
drop table #XmlImportTest
CREATE TABLE #XmlImportTest(
xmlFileName VARCHAR(300) NOT NULL,
xml_data XML NOT NULL
);
declare @xmlpath varchar(200) = 'Location of file'
declare @xmlFileName varchar(200) = @xmlpath+@xmlFile+'.xml'
--– dynamic sql is just so we can use @xmlFileName variable in OPENROWSET
EXEC('INSERT INTO #XmlImportTest(xmlFileName, xml_data)
SELECT ''' + @xmlFileName + ''', xmlData
FROM(
SELECT *
FROM OPENROWSET (BULK ''' + @xmlFileName + ''', SINGLE_BLOB) AS XMLDATA
) AS FileImport (XMLDATA)
')
DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)
select @xml = (SELECT xml_data from #XmlImportTest)
--select @xml
;with xmlnamespaces (
'http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd' as multiple,
'http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd' as submission
)
select
header.value(N'(submission:Identifiers/submission:CertificateID/text())[1]', N'nvarchar(20)') as ecert_number
from @xml.nodes('/submission:Certificate') as ci(header)
这个return没什么。
我也试过这个:
from
@xml.nodes('/submission:batch_request/submission:raise_eligibility_document/submission:Certificate') as ci(header)
我也试过使用下面的提交名称space
;with xmlnamespaces (
'http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd' as multiple,
--'http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd' as submission ,
'http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd' as submission
)
我还是什么都没有..请问我哪里错了?
Certificate
不是文档的根节点,因此 @xml.nodes('/submission:Certificate')
似乎不正确。请尝试以下操作(注意 //
):
with xmlnamespaces (
'http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd' as multiple,
'http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd' as submission
)
select
header.value(N'(submission:Identifiers/submission:CertificateID/text())[1]', N'nvarchar(20)') as ecert_number
from @xml.nodes('//submission:Certificate') as ci(header);
这是如何正确执行的完整重现。
要提及的要点:
- 只有两个命名空间与所提供的 XML 摘录相关。之一
它们是一个默认的命名空间,所以不需要它的前缀。第二
命名空间需要 'ed' 前缀。
- 现在两个位置都有正确的 XPath 表达式,即
.nodes()
和 .value()
XQuery 方法。
SQL
DECLARE @xml XML =
N'<batch_request xmlns="http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd batchsubmission- schema.xsd">
<raise_eligibility_document>
<ed:Certificate xmlns="http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd"
xmlns:ed="http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd">
<ed:Identifiers>
<ed:CertificateID>26920</ed:CertificateID>
<ed:TemplateID>ED1</ed:TemplateID>
</ed:Identifiers>
<ed:DepartureDate>2021-03-10</ed:DepartureDate>
<ed:Parties>
<ed:ConsignorID>XX345</ed:ConsignorID>
<ed:ConsigneeID>FLIGHT1</ed:ConsigneeID>
</ed:Parties>
</ed:Certificate>
</raise_eligibility_document>
</batch_request>';
WITH XMLNAMESPACES (DEFAULT 'http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd'
, 'http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd' AS ed)
SELECT c.value('(ed:Identifiers/ed:CertificateID/text())[1]', 'VARCHAR(30)') AS CertificateID
, c.value('(ed:Identifiers/ed:TemplateID/text())[1]', 'VARCHAR(30)') AS TemplateID
, c.value('(ed:DepartureDate/text())[1]', 'DATE') AS DepartureDate
, c.value('(ed:Parties/ed:ConsignorID/text())[1]', 'VARCHAR(30)') AS ConsignorID
, c.value('(ed:Parties/ed:ConsigneeID/text())[1]', 'VARCHAR(30)') AS ConsigneeID
FROM @xml.nodes('/batch_request/raise_eligibility_document/ed:Certificate') AS t(c);
输出
+---------------+------------+---------------+-------------+-------------+
| CertificateID | TemplateID | DepartureDate | ConsignorID | ConsigneeID |
+---------------+------------+---------------+-------------+-------------+
| 26920 | ED1 | 2021-03-10 | XX345 | FLIGHT1 |
+---------------+------------+---------------+-------------+-------------+
我有一个 XML 文件需要修改。
我可以在 SQL 中很好地加载文件,但是当我尝试读取一些节点时,我什么也没得到 returned.. 也没有错误。我做错了什么?
我的 XML 的开头是这样的:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<batch_request xmlns="http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd batchsubmission- schema.xsd">
<raise_eligibility_document>
<ed:Certificate xmlns="http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd" xmlns:ed="http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd">
<ed:Identifiers>
<ed:CertificateID>26920</ed:CertificateID>
<ed:TemplateID>ED1</ed:TemplateID>
</ed:Identifiers>
<ed:DepartureDate>2021-03-10</ed:DepartureDate>
<ed:Parties>
<ed:ConsignorID>XX345</ed:ConsignorID>
<ed:ConsigneeID>FLIGHT1</ed:ConsigneeID>
</ed:Parties>
这是我的 SQL 加载和读取此文件的语句以及我对 return 节点的尝试。
Declare @xmlFile VARCHAR(30) = 'TESTING'
if OBJECT_ID('tempdb..#XmlImportTest') is not null
drop table #XmlImportTest
CREATE TABLE #XmlImportTest(
xmlFileName VARCHAR(300) NOT NULL,
xml_data XML NOT NULL
);
declare @xmlpath varchar(200) = 'Location of file'
declare @xmlFileName varchar(200) = @xmlpath+@xmlFile+'.xml'
--– dynamic sql is just so we can use @xmlFileName variable in OPENROWSET
EXEC('INSERT INTO #XmlImportTest(xmlFileName, xml_data)
SELECT ''' + @xmlFileName + ''', xmlData
FROM(
SELECT *
FROM OPENROWSET (BULK ''' + @xmlFileName + ''', SINGLE_BLOB) AS XMLDATA
) AS FileImport (XMLDATA)
')
DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)
select @xml = (SELECT xml_data from #XmlImportTest)
--select @xml
;with xmlnamespaces (
'http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd' as multiple,
'http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd' as submission
)
select
header.value(N'(submission:Identifiers/submission:CertificateID/text())[1]', N'nvarchar(20)') as ecert_number
from @xml.nodes('/submission:Certificate') as ci(header)
这个return没什么。
我也试过这个:
from
@xml.nodes('/submission:batch_request/submission:raise_eligibility_document/submission:Certificate') as ci(header)
我也试过使用下面的提交名称space
;with xmlnamespaces (
'http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd' as multiple,
--'http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd' as submission ,
'http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd' as submission
)
我还是什么都没有..请问我哪里错了?
Certificate
不是文档的根节点,因此 @xml.nodes('/submission:Certificate')
似乎不正确。请尝试以下操作(注意 //
):
with xmlnamespaces (
'http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd' as multiple,
'http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd' as submission
)
select
header.value(N'(submission:Identifiers/submission:CertificateID/text())[1]', N'nvarchar(20)') as ecert_number
from @xml.nodes('//submission:Certificate') as ci(header);
这是如何正确执行的完整重现。
要提及的要点:
- 只有两个命名空间与所提供的 XML 摘录相关。之一 它们是一个默认的命名空间,所以不需要它的前缀。第二 命名空间需要 'ed' 前缀。
- 现在两个位置都有正确的 XPath 表达式,即
.nodes()
和.value()
XQuery 方法。
SQL
DECLARE @xml XML =
N'<batch_request xmlns="http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd batchsubmission- schema.xsd">
<raise_eligibility_document>
<ed:Certificate xmlns="http://sancrt.mpi.govt.nz/ecert/2013/ed-multiple-submission-schema.xsd"
xmlns:ed="http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd">
<ed:Identifiers>
<ed:CertificateID>26920</ed:CertificateID>
<ed:TemplateID>ED1</ed:TemplateID>
</ed:Identifiers>
<ed:DepartureDate>2021-03-10</ed:DepartureDate>
<ed:Parties>
<ed:ConsignorID>XX345</ed:ConsignorID>
<ed:ConsigneeID>FLIGHT1</ed:ConsigneeID>
</ed:Parties>
</ed:Certificate>
</raise_eligibility_document>
</batch_request>';
WITH XMLNAMESPACES (DEFAULT 'http://sancrt.mpi.govt.nz/ecert/2013/batch-submission-schema.xsd'
, 'http://sancrt.mpi.govt.nz/ecert/2013/ed-submission-schema.xsd' AS ed)
SELECT c.value('(ed:Identifiers/ed:CertificateID/text())[1]', 'VARCHAR(30)') AS CertificateID
, c.value('(ed:Identifiers/ed:TemplateID/text())[1]', 'VARCHAR(30)') AS TemplateID
, c.value('(ed:DepartureDate/text())[1]', 'DATE') AS DepartureDate
, c.value('(ed:Parties/ed:ConsignorID/text())[1]', 'VARCHAR(30)') AS ConsignorID
, c.value('(ed:Parties/ed:ConsigneeID/text())[1]', 'VARCHAR(30)') AS ConsigneeID
FROM @xml.nodes('/batch_request/raise_eligibility_document/ed:Certificate') AS t(c);
输出
+---------------+------------+---------------+-------------+-------------+
| CertificateID | TemplateID | DepartureDate | ConsignorID | ConsigneeID |
+---------------+------------+---------------+-------------+-------------+
| 26920 | ED1 | 2021-03-10 | XX345 | FLIGHT1 |
+---------------+------------+---------------+-------------+-------------+