【问题标题】:Select XML multiple only a few nodes with the same name选择 XML 多个仅具有相同名称的几个节点
【发布时间】:2017-12-14 10:52:21
【问题描述】:

我正在尝试构建一个肥皂消息,并且我能够使用单个选择来构建整个消息。除了问题是,在少数情况下,相同的节点名称会重复两次。

例如,所需的输出结果应该是这样的,有两个独立的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]?我在这里遗漏了什么还是符号应该不同?构建所需结果的最简单方法是什么?

【问题讨论】:

    标签: sql-server xml xpath


    【解决方案1】:

    根据您的问题,我假设这不是表格数据,而是固定值,并且您正在创建一份医疗文档,可能是一份 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 自己的答案!很棒的发现,值得一票!

    【讨论】:

    • 感谢您的回答,是的,我正在使用它来创建 CDA(临床文档架构)消息。
    【解决方案2】:

    对 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
    

    【讨论】:

    • 太棒了!我不知道这个!谢谢分享
    • 避免子选择非常好。特别是当您需要添加命名空间时,有一个非常烦人的功能,即命名空间会一遍又一遍地重复。这并没有错,而是炸毁了输出。 There's a 10(!!!) years old connect issue。你可以去那里投票...
    【解决方案3】:

    这应该可以完成工作:

    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');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多