从每个标签的下一个节点检索关联值

Retrieve associated value from next node for each tag

我有以下 XML:

<Envelope format="ProceedoOrderTransaction2.1">
  <Sender>SENDER</Sender>
  <Receiver>RECEIVER</Receiver>
  <EnvelopeID>xxxxx</EnvelopeID>
  <Date>2021-05-06</Date>
  <Time>11:59:46</Time>
  <NumberOfOrder>1</NumberOfOrder>
  <Order>
    <Header>
      <OrderNumber>POXXXXX</OrderNumber>
    </Header>
    <Lines>
      <Line>
        <LineNumber>1</LineNumber>
        <ItemName>Ipsum Lorum</ItemName>
        <SupplierArticleNumber>999999</SupplierArticleNumber>
        <UnitPrice vatRate="25.0">50</UnitPrice>
        <UnitPriceBasis>1</UnitPriceBasis>
        <OrderedQuantity unit="Styck">200</OrderedQuantity>
        <AdditionalItemProperty Key="ARTIKELNUMMER" Description="Unik ordermärkning (artikelnummer):" />
        <Value>999999</Value>
        <AdditionalItemProperty Key="BESKRIVNING" Description="Kort beskrivning:" />
        <Value>Ipsum Lorum</Value>
        <AdditionalItemProperty Key="BSKRIVNING" Description="Beskrivning:" />
        <Value>Ipsum Lorum</Value>
        <AdditionalItemProperty Key="ENHET" Description="Enhet:" />
        <Value>Styck</Value>
        <AdditionalItemProperty Key="KVANTITET" Description="Kvantitet:" />
        <Value>200</Value>
        <AdditionalItemProperty Key="PRIS" Description="Pris/Enhet (ex. moms):" />
        <Value>50</Value>
        <AdditionalItemProperty Key="VALUTA" Description="Valuta:" />
        <Value>SEK</Value>
        <Accounting>
          <AccountingLine amount="10000">
            <AccountingValue dimensionPosition="001" dimensionExternalID="ACCOUNT">xxx</AccountingValue>
            <AccountingValue dimensionPosition="002" dimensionExternalID="F1">Ipsum Lorum</AccountingValue>
            <AccountingValue dimensionPosition="005" dimensionExternalID="F3">1</AccountingValue>
            <AccountingValue dimensionPosition="010" dimensionExternalID="F2">9999</AccountingValue>
          </AccountingLine>
        </Accounting>
      </Line>
    </Lines>
  </Order>
</Envelope>

我能够正确地将所有值解析为 table 结构,但 1 个值除外,以确保它与其标签相关联的方式。所以我绊倒的地方是我正确地得到每个 AdditionalItemProperty 1 行并且我能够得到 KeyDescription 标签值,例如 BESKRIVNINGKort beskrivning:,但我无法(以合理的方式)获取 <Value> </Value> 括号之间的值,该值也与每个标签值相关联。因此,对于标签键值 BESKRIVNING ,关联值是 99999,它似乎与它关联的 AdditionalItemProperty 处于同一层次结构级别(我知道这很疯狂)。似乎他们使用的逻辑是 AdditionalItemProperty 的值将遵循 AdditionalItemProperty 标签。

我正在使用 SQL Server 2019。我已经走到这一步了:

-- Purchaseorderrowattributes
select top(10)
    i.value(N'(./Header/OrderNumber/text())[1]', 'nvarchar(30)') as OrderNumber,
    ap.value(N'(../LineNumber/text())[1]', 'nvarchar(30)') as LineNumber,
    ap.value(N'(@Description)', 'nvarchar(50)') property_description
from
    load.proceedo_orders t
outer apply 
    t.xml_data.nodes('Envelope/Order') AS i(i)
outer apply 
    i.nodes('Lines/Line/AdditionalItemProperty') as ap(ap)
where 
    file_name = @filename

产生以下输出:

OrderNumber LineNumber  property_description
--------------------------------------------
PO170006416     1       Antal timmar
PO170006416     1       Beskrivning
PO170006416     1       Kompetensområde
PO170006416     1       Roll
PO170006416     1       Ordernummer
PO170006416     1       Timpris

我找不到以正确方式为每个 属性 添加值的方法。由于值的排序将始终与 AdditionalItemProperty 的排序相同,我找到了获得 AdditionalItemProperty 排序的解决方案,然后我可以使用 rownumber,然后我希望将 rownumber 值输入到

中的括号中
ap.value(N'(../Value/text())[1]', 'nvarchar(50)') property_description

但是 SQL 服务器抛出异常,它必须是字符串文字。

所以要清楚我尝试用类似的东西做什么:

ap.value(CONCAT( N'(../Value/text())[', CAST(ROWNUMBER as varchar) ,']'), 'nvarchar(50)') property_description

SQL 服务器使用 XQuery 1.0.

您可以使用 >> 节点比较运算符来查找 Value 兄弟节点,代码类似于以下内容:

-- Purchaseorderrowattributes
select top(10)
  i.value(N'(./Header/OrderNumber/text())[1]', 'nvarchar(30)') as  OrderNumber
  ,ap.value(N'(../LineNumber/text())[1]', 'nvarchar(30)') as LineNumber
  ,ap.value(N'(@Description)', 'nvarchar(50)') property_description
  ,ap.query('
    let $property := .
    return (../Value[. >> $property][1])/text()
  ').value('.[1]', 'varchar(20)') as property_value
from load.proceedo_orders t
outer apply t.xml_data.nodes('Envelope/Order') AS i(i)
outer apply i.nodes('Lines/Line/AdditionalItemProperty') as ap(ap)
where file_name = @filename

这是怎么回事?

  • let $property := . 正在创建对当前 AdditionalItemProperty 节点的引用。
  • ../Value[. >> $property] 升序到父节点,Line,然后再次降序找到 AditionalItemProperty 节点引用之后的 Value 节点,其中 [1] 选择这些节点中的第一个。

有关更多详细信息,请参阅 3.5.3 Node Comparisons 部分。