如何在T-SQL中使用命名空间查询XML?

时间:2017-10-26 13:57:49

标签: sql-server xml tsql

我在使用命名空间查询此XML时遇到了困难。我可以在没有命名空间的情况下查询xml。

以下是我的尝试。它导致0条记录。

;WITH XMLNAMESPACES ('http://www.google.com/kml/ext/2.2' as gx)
,CTE AS
( SELECT CONVERT(XML,'<?xml version=''1.0'' encoding=''UTF-8''?>
<kml xmlns=''http://www.opengis.net/kml/2.2'' xmlns:gx=''http://www.google.com/kml/ext/2.2''>
    <Document>
        <Placemark>
            <open>1</open>
            <gx:Track>
                <altitudeMode>clampToGround</altitudeMode>
                <when>2017-10-26T11:42:05Z</when>
                <gx:coord>Lat Long Altitude</gx:coord>
                <when>2017-10-26T11:41:40Z</when>
                <gx:coord>Lat Long Altitude</gx:coord>
            </gx:Track>
        </Placemark>
    </Document>
</kml>'
        ) AS BulkColumnXML
)
SELECT altitudeModetext.node.value('.','NVARCHAR(255)') AS altitudeMode,
       gdcoordtext.node.value('.','NVARCHAR(255)') AS gdcoord,
       whentext.node.value('.','NVARCHAR(255)') AS [when]
FROM CTE
CROSS APPLY BulkColumnXML.nodes('/kml/Document/Placemark/gx:Track') as kmlDocumentPlacemarkopengxtrack(node)
CROSS APPLY kmlDocumentPlacemarkopengxtrack.node.nodes('altitudeMode/text()') as altitudeModetext(node)
CROSS APPLY kmlDocumentPlacemarkopengxtrack.node.nodes('gx:coord/text()') as gdcoordtext(node)
CROSS APPLY kmlDocumentPlacemarkopengxtrack.node.nodes('when/text()') as whentext(node)

通过在命名空间子句中添加默认命名空间来修正代码:

;WITH XMLNAMESPACES ('http://www.google.com/kml/ext/2.2' as gx,
                     DEFAULT 'http://www.opengis.net/kml/2.2')
,CTE AS
( SELECT CONVERT(XML,'<?xml version=''1.0'' encoding=''UTF-8''?>
<kml xmlns=''http://www.opengis.net/kml/2.2'' xmlns:gx=''http://www.google.com/kml/ext/2.2''>
    <Document>
        <Placemark>
            <open>1</open>
            <gx:Track>
                <altitudeMode>clampToGround</altitudeMode>
                <when>2017-10-26T11:42:05Z</when>
                <gx:coord>Lat Long Altitude</gx:coord>
                <when>2017-10-26T11:41:40Z</when>
                <gx:coord>Lat Long Altitude</gx:coord>
            </gx:Track>
        </Placemark>
    </Document>
</kml>'
        ) AS BulkColumnXML
)
SELECT altitudeModetext.node.value('.','NVARCHAR(255)') AS altitudeMode,
       gdcoordtext.node.value('.','NVARCHAR(255)') AS gdcoord,
       whentext.node.value('.','NVARCHAR(255)') AS [when]
FROM CTE
CROSS APPLY BulkColumnXML.nodes('/kml/Document/Placemark/gx:Track') as kmlDocumentPlacemarkopengxtrack(node)
CROSS APPLY kmlDocumentPlacemarkopengxtrack.node.nodes('altitudeMode/text()') as altitudeModetext(node)
CROSS APPLY kmlDocumentPlacemarkopengxtrack.node.nodes('gx:coord/text()') as gdcoordtext(node)
CROSS APPLY kmlDocumentPlacemarkopengxtrack.node.nodes('when/text()') as whentext(node)

1 个答案:

答案 0 :(得分:1)

我的魔法水晶球告诉我,你可能正在寻找这样的东西:

;WITH XMLNAMESPACES ('http://www.google.com/kml/ext/2.2' as gx,
                     DEFAULT 'http://www.opengis.net/kml/2.2')
,CTE AS
( SELECT CONVERT(XML,'<?xml version=''1.0'' encoding=''UTF-8''?>
<kml xmlns=''http://www.opengis.net/kml/2.2'' xmlns:gx=''http://www.google.com/kml/ext/2.2''>
    <Document>
        <Placemark>
            <open>1</open>
            <gx:Track>
                <altitudeMode>clampToGround</altitudeMode>
                <when>2017-10-26T11:42:05Z</when>
                <gx:coord>Lat Long Altitude</gx:coord>
                <when>2017-10-26T11:41:40Z</when>
                <gx:coord>Lat Long Altitude</gx:coord>
            </gx:Track>
        </Placemark>
    </Document>
</kml>'
) AS BulkColumnXML
)
,intermediateCTE AS
(
    SELECT CTE.BulkColumnXML.value('(/kml/Document/Placemark/open/text())[1]','NVARCHAR(255)') AS placemark_open,
           CTE.BulkColumnXML.value('(/kml/Document/Placemark/gx:Track/altitudeMode/text())[1]','nvarchar(255)') AS AltitudeMode,
           CTE.BulkColumnXML.query('/kml/Document/Placemark/gx:Track/*[local-name()!="altitudeMode"]') AS SubTree
    FROM CTE
)
,AllWhens AS 
(
SELECT intermediateCTE.placemark_open
      ,intermediateCTE.AltitudeMode
      ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS WhenIndex
      ,whn.value('text()[1]','datetime') AS WhenValue
FROM intermediateCTE
CROSS APPLY SubTree.nodes('/*:when') AS A(whn)
)
,AllCoords AS 
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS CoordIndex
      ,crd.value('text()[1]','varchar(255)') AS CoordValue
FROM intermediateCTE
CROSS APPLY SubTree.nodes('/*:coord') AS A(crd)
)
SELECT AllWhens.*
      ,AllCoords.CoordValue
FROM AllWhens
INNER JOIN AllCoords ON WhenIndex=CoordIndex 

结果

    AltitudeMode    Inx WhenValue               CoordValue
----------------------------------------------------------------
1   clampToGround   2   2017-10-26 11:41:40.000 Lat Long Altitude
1   clampToGround   1   2017-10-26 11:42:05.000 Lat Long Altitude