选择XML多个只有几个具有相同名称的节点

时间:2017-12-14 10:52:21

标签: sql-server xml xpath

我正在尝试构建一条soap消息,并且我能够使用一个select来构造整个消息。除了问题之外,仅在少数情况下,相同的节点名称重复两次。

因此,例如,所需的输出结果应该是这样的,有两个独立的id root节点:

<SoapDocument>
  <recordTarget>
    <patientRole>
      <id root="1.2.3.4" extension="1234567" />
      <id root="1.2.3.5.6" extension="0123456789" />
    </patientRole>
  </recordTarget>
</SoapDocument>

我尝试使用我对稀疏的xpath知识来构造节点名称,如下所示:

select
    '1.2.3.4'    AS 'recordTarget/patientRole/id[1]/@root',
    '1234567'    AS 'recordTarget/patientRole/id[1]/@extension',
    '1.2.3.5.6'  AS 'recordTarget/patientRole/id[2]/@root',
    '0123456789' AS 'recordTarget/patientRole/id[2]/@extension'
FOR XML PATH('SoapDocument'),TYPE

显然,xpath命名无法应用于列名id[1]id[2]吗?我在这里遗漏了什么或者记号是否有所不同?构建所需结果的最简单方法是什么?

3 个答案:

答案 0 :(得分:2)

从我的问题我假设,这不是表格数据,而是固定值,你正在创建一个医疗文件,可能是一个CDA。

试试这个:

SELECT 
(
    SELECT
        '1.2.3.4'    AS 'id/@root',
        '1234567'    AS 'id/@extension',
        '',
        '1.2.3.5.6'  AS 'id/@root',
        '0123456789' AS 'id/@extension'
    FOR XML PATH('patientRole'),TYPE
) AS [SoapDocument/recordTarget]
FOR XML PATH('')

结果:

<SoapDocument>
  <recordTarget>
    <patientRole>
      <id root="1.2.3.4" extension="1234567" />
      <id root="1.2.3.5.6" extension="0123456789" />
    </patientRole>
  </recordTarget>
</SoapDocument>

一些解释:中间的空元素允许您在一个查询中放置两个具有相同名称的元素。如何将这些内容添加到周围的标签中有各种方法。这只是一种可能性。

更新

我想指出BdR自己的答案!伟大的发现,值得投票!

答案 1 :(得分:1)

对Shnugo的回答稍微详细一点,因为它让我尝试使用“空柱”来尝试一些事情。

如果不为emtpy列指定名称,它将重置为XML根节点。因此,以下列将从您当时所在选择的XML根开始。但是,如果明确命名空分隔符列,则以下列将在该列名称设置的层次结构中继续。

因此,下面的选择也会产生所需的结果。它略有不同,但在我的情况下,它允许我避免使用子选择。

select
    '1.2.3.4'    AS 'recordTarget/patientRole/id/@root',
    '1234567'    AS 'recordTarget/patientRole/id/@extension',
    ''           AS 'recordTarget/patientRole',
    '1.2.3.5.6'  AS 'recordTarget/patientRole/id/@root',
    '0123456789' AS 'recordTarget/patientRole/id/@extension'
FOR XML PATH('SoapDocument'),TYPE

答案 2 :(得分:0)

这应该做的工作:

WITH CTE AS (
    SELECT *
    FROM (VALUES('1.2.3.4','1234567'),
                ('1.2.3.5.6','0123456789')) V ([root], [extension]))
SELECT (SELECT (SELECT (SELECT [root] AS [@root],
                               [extension] AS [@extension]
                        FROM CTE
                        FOR XML PATH('id'), TYPE)
                FOR XML PATH('patientRole'), TYPE)
        FOR XML PATH ('recordTarget'), TYPE)
FOR XML PATH ('SoapDocument');