sql-server - 抓取子级元素xml

标签 sql-server xml xpath xml-parsing xquery

我有一个 XML 包含元素作为 cargo 的运输和元素作为运输的 cargo 线。

在 1 个文件中是具有 1 个或多个元素的多个元素。

我需要以另一种格式创建 XML 文件。

所需格式:

<shipment>
--shipment lines
<cargo>
--cargo line
</cargo>
<cargo>
--cargo line
</cargo>
<cargo>
--cargo line
</cargo>
</shipment>
<shipment>
--shipment lines
<cargo>
--cargo line
</cargo>
</shipment>

当前 SQL:


set @shipmentsXML = (SELECT     
            "customer_id" = T.c.query('./ediCustomerNumber').value('.', 'varchar(50)'),
            "reference" = T.c.query('./ediReference').value('.', 'varchar(50)'),


(select

                "unitamount" = T.C.query('./quantity').value('.', 'varchar(50)'),
                "weight" = T.c.query('./grossWeight').value('.', 'varchar(50)'),
                "loadingmeter" = T.c.query('./loadingMeters').value('.', 'varchar(50)')

                FROM @Xml.nodes('./file/goodsLine') T(c)
                FOR XML PATH ('cargo'), TYPE)


FROM @Xml.nodes('manifest-out/consol') T(c)
FOR XML PATH ('shipment')
)

使用控制台标签,但没有显示 cargo 线

源 XML:

<manifest-out type="tag">
  <ediCustomerNumber>*******</ediCustomerNumber>
  <ediCustomerDepartment>Ic</ediCustomerDepartment>
  <transmitter>R</transmitter>
  <receiver>*******</receiver>
  <ediReference>*******</ediReference>
  <referenceIndication>0</referenceIndication>
  <internalShipmentNumber>*******</internalShipmentNumber>
  <ediFunction1>6</ediFunction1>
  <dateTimeZone>2019-07-24T13:05:55+02:00</dateTimeZone>
  <fileHeader type="tag">
  </fileHeader>
  <consol type="tag">
    <file type="tag">
      <operationalPeriod>2019/07</operationalPeriod>
      <loadingDate>2019-07-17</loadingDate>
      <loadingTime>00:00:00</loadingTime>
      <unloadingDate>2019-07-26</unloadingDate>
      <unloadingTime>17:00:00</unloadingTime>
      <primaryReference>8017883827</primaryReference>
      <deliveryTerm>DAP</deliveryTerm>
      <codeShedHandling>true</codeShedHandling>
      <goodsLine type="tag">
        <quantity>3.000</quantity>
        <grossWeight>415.000</grossWeight>
        <loadingMeters>1.633</loadingMeters>
      </goodsLine>
      <goodsLine type="tag">
        <quantity>1.000</quantity>
        <grossWeight>605.000</grossWeight>
        <loadingMeters>4.633</loadingMeters>
      </goodsLine>
      <goodsLine type="tag">
        <quantity>2.000</quantity>
        <grossWeight>75.000</grossWeight>
        <loadingMeters>2.633</loadingMeters>
      </goodsLine>
    </file>
  </consol>
  <consol type="tag">
    <file type="tag">
      <operationalPeriod>2019/07</operationalPeriod>
      <loadingDate>2019-07-17</loadingDate>
      <loadingTime>00:00:00</loadingTime>
      <unloadingDate>2019-07-26</unloadingDate>
      <unloadingTime>17:00:00</unloadingTime>
      <primaryReference>8017883827</primaryReference>
      <deliveryTerm>DAP</deliveryTerm>
      <codeShedHandling>true</codeShedHandling>
      <goodsLine type="tag">
        <quantity>3.000</quantity>
        <grossWeight>415.000</grossWeight>
        <loadingMeters>1.633</loadingMeters>
      </goodsLine>
    </file>
  </consol>
</manifest-out>

有人可以指出我选择好线的正确方向吗

最佳答案

您的问题缺少预期的输出,至少,我不清楚......但我希望我猜对了:

SELECT @xml.value('(/manifest-out/ediCustomerNumber/text())[1]','varchar(50)') AS customer_id 
      ,@xml.value('(/manifest-out/ediReference/text())[1]','varchar(50)') AS reference
      ,(
        SELECT gl.value('(quantity/text())[1]','decimal(14,10)') AS unitamount
              ,gl.value('(grossWeight/text())[1]','decimal(14,10)') AS [weight]
              ,gl.value('(loadingMeters/text())[1]','decimal(14,10)') AS loadingmeter
        FROM @xml.nodes('/manifest-out/consol/file/goodsLine') A(gl)
        FOR XML PATH('cargo'),TYPE
       ) 
FOR XML PATH('shipment');

结果
<shipment>
  <customer_id>*******</customer_id>
  <reference>*******</reference>
  <cargo>
    <unitamount>3.0000000000</unitamount>
    <weight>415.0000000000</weight>
    <loadingmeter>1.6330000000</loadingmeter>
  </cargo>
  <cargo>
    <unitamount>1.0000000000</unitamount>
    <weight>605.0000000000</weight>
    <loadingmeter>4.6330000000</loadingmeter>
  </cargo>
  <cargo>
    <unitamount>2.0000000000</unitamount>
    <weight>75.0000000000</weight>
    <loadingmeter>2.6330000000</loadingmeter>
  </cargo>
</shipment>

简而言之:

我们可以选择1:1相关值(您的货件数据)直接来自 XML 并在 <shipment> 内返回.
嵌套 SELECT将选择 <goodsLine> 下面的重复元素并在 <cargo> 内返回它们中的每一个.

顺便说一句:你自己的代码非常非常接近......

如果您将内部 XPath 更改为 /manifest-out/consol/file/goodsLine,它将起作用。或者如果您使用 T.c.nodes() .您正在尝试使用相对路径 ./file/goodsLine针对源 XML。您甚至可以使用 FROM @xml.nodes('//goodsLine') T(c) 进行深度搜索。 ,但一般建议是:尽可能具体。

关于sql-server - 抓取子级元素xml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57357800/

相关文章:

xml - 将 XML 文件加载到 Hive 表

c# - 从 XPath 中检索与同一节点中的另一个属性值相匹配的属性值

c# - 如何迭代 linq-to-sql 查询结果的结果并追加结果?

c# - 拆分xml文件并保留父节点信息

c# - 单个元素的 Xml 序列化覆盖

xml - XSLT + 创建表结构

xml - 什么版本的 XPath 在 XML::LibXML 中实现?

sql - Group By 和 STUFF 在 sql server 中的组合结果

sql-server - SQL Server 2008 R2 bug 还是什么?

sql - 使用 Sql Server 集成服务连接到 Oracle 数据库