T-SQL 从 XML 节点获取值,如果节点存在并且适合模式
T-SQL get value from XML node if node exists and fits schema
我正在尝试从 KML 文件源读取数据。我需要阅读的部分内容是样式信息。不同的样式规则在根级别声明为 <Style>
节点,其中包含不同数量的信息。我只对定义线条颜色和多边形填充颜色的样式感兴趣。这是我目前的做法:
样本xml:
<Document>
<Style id="default">
</Style>
<Style id="hl">
<IconStyle>
<scale>1.2</scale>
</IconStyle>
</Style>
<Style id="White-Style">
<LineStyle>
<color>FFFFFFFF</color>
</LineStyle>
<PolyStyle>
<color>FFFFFFFF</color>
</PolyStyle>
</Style>
<Style id="Black-Style">
<LineStyle>
<color>FF000000</color>
</LineStyle>
<PolyStyle>
<color>FF000000</color>
</PolyStyle>
</Style>
<Placemark> ... </Placemark>
...
</Document>
我的SQL代码:
declare @style table( style_id nvarchar(50), line_color nchar(8), fill_color nchar(8) )
;with xmlnamespaces('http://www.opengis.net/kml/2.2'AS K)
insert into @style
select
T.A.value('(@K:id)[1]', 'nvarchar(50)'),
T.A.value('/K:LineStyle[1]/K:color[1]/.', 'nchar(8)'),
T.A.value('/K:PolyStyle[1]/K:color[1]/.', 'nchar(8)')
from @xml_data.nodes('//K:Style') as T(A)
where @xml_data.exist('//K:Style/K:PolyStyle/K:color') = 1 and @xml_data.exist('//K:Style/K:LineStyle/K:color') = 1
这种方法的问题在于,@xml_data、作为一个整体、returns在两个exist()
方法上都是正确的,这意味着 value()
方法在尝试从 <Style id="default">
和 <Style id="h1">
.
检索规则时会抛出错误
我还尝试了以下两个片段:
select
...
(case T.A.exists('/K:LineStyle[1]/K:color') = 1 then T.A.value('/K:LineStyle[1]/K:color[1]/.', 'nchar(8)') else null end)
和
where T.A.exist('/K:PolyStyle[1]/K:color') = 1 and T.A.exist('/K:LineStyle[1]/K:color') = 1
但是,以上两个都会产生以下错误:The column 'A' that was returned from the nodes() method cannot be used directly. It can only be used with one of the four XML data type methods, exist(), nodes(), query(), and value(), or in IS NULL and IS NOT NULL checks
您可能会发现将所有 XML 拉入您的 table 变量或临时 table 会更高效(更不用说更容易解决丢失数据等潜在问题) ,然后 select 来自 table ,其中所需的列不为空。
DECLARE @StyleXML XML
SET @StyleXML =
'<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Style id="default">
</Style>
<Style id="hl">
<IconStyle>
<scale>1.2</scale>
</IconStyle>
</Style>
<Style id="White-Style">
<LineStyle>
<color>FFFFFFFF</color>
</LineStyle>
<PolyStyle>
<color>FFFFFFFF</color>
</PolyStyle>
</Style>
<Style id="Black-Style">
<LineStyle>
<color>FF000000</color>
</LineStyle>
<PolyStyle>
<color>FF000000</color>
</PolyStyle>
</Style>
<Placemark> ... </Placemark>
...
</Document>'
SELECT
T.A.value('(@id)[1]', 'nvarchar(50)') AS ID
,T.A.value('./LineStyle[1]/color[1]/.', 'varchar(8)') AS LSColor
,T.A.value('./PolyStyle[1]/color[1]/.', 'varchar(8)') AS PSColor
INTO #Style
FROM @StyleXML.nodes('Document/Style') AS T(A)
SELECT *
FROM #Style
WHERE LSColor IS NOT NULL
AND PSColor IS NOT NULL
我正在尝试从 KML 文件源读取数据。我需要阅读的部分内容是样式信息。不同的样式规则在根级别声明为 <Style>
节点,其中包含不同数量的信息。我只对定义线条颜色和多边形填充颜色的样式感兴趣。这是我目前的做法:
样本xml:
<Document>
<Style id="default">
</Style>
<Style id="hl">
<IconStyle>
<scale>1.2</scale>
</IconStyle>
</Style>
<Style id="White-Style">
<LineStyle>
<color>FFFFFFFF</color>
</LineStyle>
<PolyStyle>
<color>FFFFFFFF</color>
</PolyStyle>
</Style>
<Style id="Black-Style">
<LineStyle>
<color>FF000000</color>
</LineStyle>
<PolyStyle>
<color>FF000000</color>
</PolyStyle>
</Style>
<Placemark> ... </Placemark>
...
</Document>
我的SQL代码:
declare @style table( style_id nvarchar(50), line_color nchar(8), fill_color nchar(8) )
;with xmlnamespaces('http://www.opengis.net/kml/2.2'AS K)
insert into @style
select
T.A.value('(@K:id)[1]', 'nvarchar(50)'),
T.A.value('/K:LineStyle[1]/K:color[1]/.', 'nchar(8)'),
T.A.value('/K:PolyStyle[1]/K:color[1]/.', 'nchar(8)')
from @xml_data.nodes('//K:Style') as T(A)
where @xml_data.exist('//K:Style/K:PolyStyle/K:color') = 1 and @xml_data.exist('//K:Style/K:LineStyle/K:color') = 1
这种方法的问题在于,@xml_data、作为一个整体、returns在两个exist()
方法上都是正确的,这意味着 value()
方法在尝试从 <Style id="default">
和 <Style id="h1">
.
检索规则时会抛出错误
我还尝试了以下两个片段:
select
...
(case T.A.exists('/K:LineStyle[1]/K:color') = 1 then T.A.value('/K:LineStyle[1]/K:color[1]/.', 'nchar(8)') else null end)
和
where T.A.exist('/K:PolyStyle[1]/K:color') = 1 and T.A.exist('/K:LineStyle[1]/K:color') = 1
但是,以上两个都会产生以下错误:The column 'A' that was returned from the nodes() method cannot be used directly. It can only be used with one of the four XML data type methods, exist(), nodes(), query(), and value(), or in IS NULL and IS NOT NULL checks
您可能会发现将所有 XML 拉入您的 table 变量或临时 table 会更高效(更不用说更容易解决丢失数据等潜在问题) ,然后 select 来自 table ,其中所需的列不为空。
DECLARE @StyleXML XML
SET @StyleXML =
'<?xml version="1.0" encoding="UTF-8"?>
<Document>
<Style id="default">
</Style>
<Style id="hl">
<IconStyle>
<scale>1.2</scale>
</IconStyle>
</Style>
<Style id="White-Style">
<LineStyle>
<color>FFFFFFFF</color>
</LineStyle>
<PolyStyle>
<color>FFFFFFFF</color>
</PolyStyle>
</Style>
<Style id="Black-Style">
<LineStyle>
<color>FF000000</color>
</LineStyle>
<PolyStyle>
<color>FF000000</color>
</PolyStyle>
</Style>
<Placemark> ... </Placemark>
...
</Document>'
SELECT
T.A.value('(@id)[1]', 'nvarchar(50)') AS ID
,T.A.value('./LineStyle[1]/color[1]/.', 'varchar(8)') AS LSColor
,T.A.value('./PolyStyle[1]/color[1]/.', 'varchar(8)') AS PSColor
INTO #Style
FROM @StyleXML.nodes('Document/Style') AS T(A)
SELECT *
FROM #Style
WHERE LSColor IS NOT NULL
AND PSColor IS NOT NULL