XPath查询在联机XPath测试程序中工作正常但在SQL Server中没有

时间:2017-05-15 12:25:06

标签: sql-server xml xpath

我有一块XML,我必须在SQL Server中粉碎。到目前为止,我已经取得了部分成功,但是尽管我在网上找到并尝试了几个小时的代码,但我已经没有进一步了......

在SQL代码下面,包括XML的修剪部分:

DECLARE @xml xml, @hdoc int
SET @xml = '
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.egem.nl/StUF/StUF0301" xmlns:ns2="http://www.egem.nl/StUF/sector/zkn/0310" xmlns:bg="http://www.egem.nl/StUF/sector/bg/0310">
  <SOAP-ENV:Body>
    <ns2:zakLk01>
      <ns2:object ns1:entiteittype="ZAK" ns1:verwerkingssoort="T">
        <ns2:heeftBetrekkingOp ns1:entiteittype="ZAKOBJ" ns1:verwerkingssoort="T">
          <ns2:gerelateerde>
            <ns2:natuurlijkPersoon ns1:entiteittype="NPS" ns1:verwerkingssoort="I">
              <verblijfsadres xmlns="http://www.egem.nl/StUF/sector/bg/0310">
                <gor.openbareRuimteNaam>Westmalledreef 45</gor.openbareRuimteNaam>
                <wpl.woonplaatsNaam>B-16753</wpl.woonplaatsNaam>
              </verblijfsadres>
              <voornamen xmlns="http://www.egem.nl/StUF/sector/bg/0310">Erik</voornamen>
            </ns2:natuurlijkPersoon>
          </ns2:gerelateerde>
        </ns2:heeftBetrekkingOp>
      </ns2:object>
    </ns2:zakLk01>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
'

EXEC sp_xml_preparedocument 
@hDoc OUTPUT, 
@XML,
'<root xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:ns1="http://www.egem.nl/StUF/StUF0301" 
    xmlns:ns2="http://www.egem.nl/StUF/sector/zkn/0310"
    xmlns:bg="http://www.egem.nl/StUF/sector/bg/0310>"/>'


SELECT * FROM OPENXML(@hdoc, '/SOAP-ENV:Envelope') --Row Pattern
WITH 
(
Voornamen VARCHAR(50) './/ns2:heeftBetrekkingOp/ns2:gerelateerde/ns2:natuurlijkPersoon/bg:voornamen',
Adres VARCHAR(100) './/ns2:heeftBetrekkingOp/ns2:gerelateerde/ns2:natuurlijkPersoon/bg:verblijfsadres/bg:gor.openbareRuimteNaam'
)

EXEC sp_xml_removedocument @hdoc --Releasing memory

当我使用同一段XML在https://www.freeformatter.com/xpath-tester.html上尝试两个XPath查询时,它们工作得很好,并且还给了我“voornamen”和“openbareRuimteNaam”的值。在SQL中,无论我尝试什么,它们都会返回NULL。我一定做错了什么。有人能指出我正确的方向吗?

我已经尝试过SQL Server 2014以及2016年。

2 个答案:

答案 0 :(得分:1)

您可以使用 Configuration cfg = new Configuration() .addAnnotatedClass(org.entity.Person.class); 方法代替.value

示例解决方案:

OPENXML

当然深度搜索;WITH XMLNAMESPACES ( 'http://schemas.xmlsoap.org/soap/envelope/' AS [SOAP-ENV], 'http://www.egem.nl/StUF/StUF0301' AS ns1, 'http://www.egem.nl/StUF/sector/zkn/0310' AS ns2, 'http://www.egem.nl/StUF/sector/bg/0310' AS bg ) SELECT @xml.value('(//bg:voornamen/text())[1]','VARCHAR(50)') AS Voornamen, @xml.value('(//bg:gor.openbareRuimteNaam/text())[1]','VARCHAR(100)') AS Adres 不是好习惯。更好的是指定每个节点号:

//

答案 1 :(得分:0)

原因

这个XML是如何生成的?你遇到的问题是:

<verblijfsadres xmlns="http://www.egem.nl/StUF/sector/bg/0310">
  <gor.openbareRuimteNaam>Westmalledreef 45</gor.openbareRuimteNaam>
  <wpl.woonplaatsNaam>B-16753</wpl.woonplaatsNaam>
</verblijfsadres>
<voornamen xmlns="http://www.egem.nl/StUF/sector/bg/0310">Erik</voornamen>

您使用与其他命名空间相同的URL声明新的默认命名空间

在下面的代码中,我删除了这些额外的命名空间,并使用您的代码进行了微小的更改:voornamengor.openbareRuimteNaam没有前缀。这有效:

DECLARE @xml xml, @hdoc int
SET @xml = '
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.egem.nl/StUF/StUF0301" xmlns:ns2="http://www.egem.nl/StUF/sector/zkn/0310" xmlns:bg="http://www.egem.nl/StUF/sector/bg/0310">
  <SOAP-ENV:Body>
    <ns2:zakLk01>
      <ns2:object ns1:entiteittype="ZAK" ns1:verwerkingssoort="T">
        <ns2:heeftBetrekkingOp ns1:entiteittype="ZAKOBJ" ns1:verwerkingssoort="T">
          <ns2:gerelateerde>
            <ns2:natuurlijkPersoon ns1:entiteittype="NPS" ns1:verwerkingssoort="I">
              <verblijfsadres>
                <gor.openbareRuimteNaam>Westmalledreef 45</gor.openbareRuimteNaam>
                <wpl.woonplaatsNaam>B-16753</wpl.woonplaatsNaam>
              </verblijfsadres>
              <voornamen>Erik</voornamen>
            </ns2:natuurlijkPersoon>
          </ns2:gerelateerde>
        </ns2:heeftBetrekkingOp>
      </ns2:object>
    </ns2:zakLk01>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
'

EXEC sp_xml_preparedocument 
@hDoc OUTPUT, 
@XML,
'<root xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:ns1="http://www.egem.nl/StUF/StUF0301" 
    xmlns:ns2="http://www.egem.nl/StUF/sector/zkn/0310"
    xmlns:bg="http://www.egem.nl/StUF/sector/bg/0310>"/>'


SELECT * FROM OPENXML(@hdoc, '/SOAP-ENV:Envelope') --Row Pattern
WITH 
(
Voornamen VARCHAR(50) './/ns2:heeftBetrekkingOp/ns2:gerelateerde/ns2:natuurlijkPersoon/voornamen',
Adres VARCHAR(100) './/ns2:heeftBetrekkingOp/ns2:gerelateerde/ns2:natuurlijkPersoon/verblijfsadres/gor.openbareRuimteNaam'
)

EXEC sp_xml_removedocument @hdoc --Releasing memory

分析您的XML

尝试不使用WITH这样的原始查询

SELECT * FROM OPENXML(@hdoc, '/SOAP-ENV:Envelope')

您将获得一个列表,XML引擎如何看待您的元素(片段):

+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| natuurlijkPersoon      | ns2   | http://www.egem.nl/StUF/sector/zkn/0310 | NULL | NULL | NULL                                   |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| entiteittype           | ns1   | http://www.egem.nl/StUF/StUF0301        | NULL | NULL | NULL                                   |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| #text                  | NULL  | NULL                                    | NULL | NULL | NPS                                    |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| verwerkingssoort       | ns1   | http://www.egem.nl/StUF/StUF0301        | NULL | NULL | NULL                                   |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| #text                  | NULL  | NULL                                    | NULL | NULL | I                                      |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| verblijfsadres         | NULL  | http://www.egem.nl/StUF/sector/bg/0310  | NULL | NULL | NULL                                   |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| xmlns                  | xmlns | NULL                                    | NULL | NULL | NULL                                   |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| #text                  | NULL  | NULL                                    | NULL | NULL | http://www.egem.nl/StUF/sector/bg/0310 |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| gor.openbareRuimteNaam | NULL  | http://www.egem.nl/StUF/sector/bg/0310  | NULL | NULL | NULL                                   |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| #text                  | NULL  | NULL                                    | NULL | NULL | Westmalledreef 45                      |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| wpl.woonplaatsNaam     | NULL  | http://www.egem.nl/StUF/sector/bg/0310  | NULL | 20   | NULL                                   |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| #text                  | NULL  | NULL                                    | NULL | NULL | B-16753                                |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+
| voornamen              | NULL  | http://www.egem.nl/StUF/sector/bg/0310  | NULL | 18   | NULL                                   |
+------------------------+-------+-----------------------------------------+------+------+----------------------------------------+

您可以看到,您要查找的元素位于命名空间中,但没有前缀...

所有这些只是解释为什么您的查询不起作用的一些原因。但是:

你应该使用不同的方法!

FROM OPENXML与相应的SP准备和删除文档已经过时,不应再使用(很少有例外)。而是使用适当的methods the XML data type provides

尽可能明确,最好是这样:

;WITH XMLNAMESPACES (
'http://schemas.xmlsoap.org/soap/envelope/' AS [SOAP-ENV],
'http://www.egem.nl/StUF/StUF0301' AS ns1,
'http://www.egem.nl/StUF/sector/zkn/0310' AS ns2,
'http://www.egem.nl/StUF/sector/bg/0310' AS bg
)

SELECT @xml.value('(SOAP-ENV:Envelope/SOAP-ENV:Body/ns2:zakLk01/ns2:object/ns2:heeftBetrekkingOp/ns2:gerelateerde/ns2:natuurlijkPersoon/bg:voornamen/text())[1]','VARCHAR(50)') AS Voornamen
      ,@xml.value('(SOAP-ENV:Envelope/SOAP-ENV:Body/ns2:zakLk01/ns2:object/ns2:heeftBetrekkingOp/ns2:gerelateerde/ns2:natuurlijkPersoon/bg:verblijfsadres/bg:gor.openbareRuimteNaam/text())[1]','VARCHAR(100)') AS Adres

这是简单而丑陋的

SELECT @xml.value('(//*:natuurlijkPersoon/*:voornamen/text())[1]','VARCHAR(50)') AS Voornamen
      ,@xml.value('(//*:natuurlijkPersoon/*:verblijfsadres/*:gor.openbareRuimteNaam/text())[1]','VARCHAR(100)') AS Adres