PostgreSQL Xpath选择元素及其子属性为两列

Gai*_*war 4 xml postgresql xpath

我在postgreSQL中有一个表历史记录(id int,内容xml)。其中一个ID的XML内容如下

<history-data>
      <history recorded-date="20110601">
        <assignees>
          <assignee>
             <last-name>CIENA LUXEMBOURG</last-name>
          </assignee>
        </assignees>
        <assignors>
          <assignor execution-date="20110517">
              <last-name>NORTEL NETWORKS LIMITED</last-name>
          </assignor>
        </assignors>
      </history>
      <history recorded-date="20110601">
        <assignees>
          <assignee>
              <last-name>CIENA CORPORATION</last-name>
          </assignee>
        </assignees>
        <assignors>
          <assignor execution-date="20110527">
              <last-name>CIENA LUXEMBOURG</last-name>
          </assignor>
        </assignors>
      </history>
      <history recorded-date="20090430">
        <assignees>
          <assignee>
             <last-name>NORTEL NETWORKS</last-name> 
          </assignee>
        </assignees>
        <assignors>
          <assignor execution-date="20090424">
              <last-name>MAK, GARY</last-name>
          </assignor>
          <assignor execution-date="20090424">
              <last-name>VELEZ, EDGAR</last-name>
          </assignor>
        </assignors>
      </history>
    </history-data>
Run Code Online (Sandbox Code Playgroud)

在这里,我想获取姓氏及其相应的执行日期。对于上面的示例,我想要以下输出

last-name                   execution-date
================            ==============
CIENA LUXEMBOURG              20110517
CIENA CORPORATION             20110527
NORTEL NETWORKS               20090424
Run Code Online (Sandbox Code Playgroud)

我可以使用以下SQL查询生成所有可能的组合,但无法获得上述输出

SELECT id, unnest(CAST(xpath('/history-data/history/assignees/assignee/last-name/text()',content) AS text)::text[]) AS last-name,
unnest(CAST(xpath('/history-data/history/assignors/assignor/@execution-date',content) AS text)::text[]) AS execution-date
FROM history
WHERE id = 10
Run Code Online (Sandbox Code Playgroud)

关于如何做到这一点的任何建议?

Dmi*_*kov 5

您需要遍历所有history节点并获得具有xpath()功能的适当元素。默认情况下,XPath的提取收益的结果阵列XML,这就是为什么我们需要得到与数组索引的实际值(...)[1]; 示例查询可能如下:

SELECT
  (xpath('//assignee/last-name/text()',xml_element))[1] AS "last-name",
  (xpath('//assignor/@execution-date',xml_element))[1] AS "execution-date"
FROM (
  SELECT unnest(xpath('//history',content)) AS xml_element FROM history
  WHERE id = 10
) t;
Run Code Online (Sandbox Code Playgroud)

结果是:

     last-name     | execution-date 
-------------------+----------------
 CIENA LUXEMBOURG  | 20110517
 CIENA CORPORATION | 20110527
 NORTEL NETWORKS   | 20090424
(3 rows)
Run Code Online (Sandbox Code Playgroud)

assignees有多个assagnee节点时,查询unnest()应用于获取所有数组元素:

SELECT
  unnest(xpath('//assignee/last-name/text()',xml_element)) AS "last-name",
  unnest(xpath('//assignor/@execution-date',xml_element)) AS "execution-date"
FROM (
  SELECT unnest(xpath('//history',content)) AS xml_element FROM history
  WHERE id = 10
) t;
Run Code Online (Sandbox Code Playgroud)