SQL Server:如何在select查询中使用XPATH

时间:2015-12-03 16:45:12

标签: sql-server xml xpath

我在SQL Server中有一个表,其中包含一个XML数据类型的列。例如,一个值看起来像

<doc>

<q></q>

<p1>
    <p2 dd="ert" ji="pp">

        <p3>1</p3>
        <p3>2</p3>
        <p3>XYZ</p3>
        <p3>3</p3>

     </p2>

     <p2 dd="ert" ji="pp">

        <p3>4</p3>
        <p3>5</p3>
        <p3>ABC</p3>
        <p3>6</p3>

     </p2>

</p1>
<r></r>
<p1>
    <p2 dd="ert" ji="pp">

        <p3>7</p3>
        <p3>8</p3>
        <p3>ABC</p3>
        <p3>9</p3>

     </p2>

     <p2 dd="ert" ji="pp">

        <p3>10</p3>
        <p3>11</p3>
        <p3>XYZ</p3>
        <p3>12</p3>

     </p2>

</p1>
</doc>

现在,我想执行以下xpath

./doc//p1/p2/p3[contains(text(),'ABC') or contains(text(),'XYZ')]/preceding-sibling::p3

所以结果是

1 2 4 5 7 8 10 11

所以我想选择所有<p3>节点作为<p3>节点的兄弟节点,文本为ABC或XYZ。此外,这些<p3>节点必须位于<p2>个节点内<p1>个节点内。截至目前,我只是按原样选择列,然后在python中使用xpath来获取节点。有没有办法使用SQL select查询获取所需的节点?

修改

请注意即使我有

也足够了
<p3>1</p3>
        <p3>2</p3>
<p3>4</p3>
        <p3>5</p3>
<p3>7</p3>
        <p3>8</p3>
<p3>10</p3>
        <p3>11</p3>

因为那时我可以轻松使用XML解析器来获取文本。

2 个答案:

答案 0 :(得分:1)

从另一个角度思考。使用您实际感兴趣的p3元素启动XPath表达式。使用以下表达式:

/doc/p1/p2/p3[following-sibling::p3 = 'ABC' or following-sibling::p3 = 'XYZ']

甚至

/doc/p1/p2/p3[following-sibling::p3[. = 'ABC' or . = 'XYZ']]

将检索(由---------分隔的单个结果):

<p3>1</p3>
-----------------------
<p3>2</p3>
-----------------------
<p3>4</p3>
-----------------------
<p3>5</p3>
-----------------------
<p3>7</p3>
-----------------------
<p3>8</p3>
-----------------------
<p3>10</p3>
-----------------------
<p3>11</p3>

答案 1 :(得分:1)

在SQL Server的XPath / XQuery中需要考虑一些限制,即不支持following-siblingpreceding-sibling。作为替代方案,您可以使用>><<运算符来比较同级元素位置。请参阅下面的演示。

在XML变量中输入XML:

declare @xml XML = '<?xml version="1.0" encoding="UTF-8"?>
<doc> 
  <q/>  
  <p1> 
    <p2 dd="ert" ji="pp"> 
      <p3>1</p3>  
      <p3>2</p3>  
      <p3>XYZ</p3>  
      <p3>3</p3> 
    </p2>  
    <p2 dd="ert" ji="pp"> 
      <p3>4</p3>  
      <p3>5</p3>  
      <p3>ABC</p3>  
      <p3>6</p3> 
    </p2> 
  </p1>  
  <r/>  
  <p1> 
    <p2 dd="ert" ji="pp"> 
      <p3>7</p3>  
      <p3>8</p3>  
      <p3>ABC</p3>  
      <p3>9</p3> 
    </p2>  
    <p2 dd="ert" ji="pp"> 
      <p3>10</p3>  
      <p3>11</p3>  
      <p3>XYZ</p3>  
      <p3>12</p3> 
    </p2> 
  </p1> 
</doc>'

查询:

SELECT @xml.query('
/doc/p1/p2/p3[. << ../p3[contains(.,"ABC") or contains(.,"XYZ")][last()]]
')

输出(在SQL Server 2008R2中测试)

<p3>1</p3>
<p3>2</p3>
<p3>4</p3>
<p3>5</p3>
<p3>7</p3>
<p3>8</p3>
<p3>10</p3>
<p3>11</p3>