我需要解析以下XML: https://www.iftach.org/taxmatrix/charts/4Q2016.xml
每个RECORD节点必须位于不同的行中:
<RECORD>
<JURISDICTION ID="#15" >AB</JURISDICTION>
<COUNTRY>CAN</COUNTRY>
<FUEL_TYPE>Gasoline</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Special Diesel</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Gasohol</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Propane</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.2700</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.0940</RATE>
<FUEL_TYPE>LNG</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.0000</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.0000</RATE>
<FUEL_TYPE>CNG</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.0000</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.0000</RATE>
<FUEL_TYPE>Ethanol</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Methanol</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>E-85</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>M-85</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>A55</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Biodiesel</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
</RECORD>
我想在我的集合中跟踪列:
这在T_SQL中是否可行?在C#中,我只是从上到下读取XML,并根据XML中的位置将TYPE连接到RATE。我在SQL中使用它更方便..
答案 0 :(得分:3)
因此,就XML而言,我认为这是更难的部分,是的,你可以:
DECLARE @xml xml = '<RECORD>
<JURISDICTION ID="#15" >AB</JURISDICTION>
<COUNTRY>CAN</COUNTRY>
<FUEL_TYPE>Gasoline</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Special Diesel</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Gasohol</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Propane</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.2700</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.0940</RATE>
<FUEL_TYPE>LNG</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.0000</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.0000</RATE>
<FUEL_TYPE>CNG</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.0000</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.0000</RATE>
<FUEL_TYPE>Ethanol</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Methanol</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>E-85</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>M-85</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>A55</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
<FUEL_TYPE>Biodiesel</FUEL_TYPE>
<RATE COUNTRY="US" RATECHANGE="0">0.3734</RATE>
<RATE COUNTRY="CAN" RATECHANGE="0">0.1300</RATE>
</RECORD>'
;WITH xCTE AS
(
SELECT @xml.query('
<Data jurisdiction="{data(/RECORD/JURISDICTION/text())}" country="{data(/RECORD/COUNTRY/text())}">
{
for $x in (/RECORD/*[local-name() = "RATE"])
return
<FuelType name="{data(/RECORD/FUEL_TYPE[. << $x][last()])}" country="{data($x/@COUNTRY)}" value="{data($x)}" />
}
</Data>
') AS DocXml
)
SELECT
x.n.value('../@jurisdiction', 'VARCHAR(10)') as Jurisdiction
,x.n.value('../@country', 'VARCHAR(5)') as Country
,x.n.value('@name', 'VARCHAR(20)') as Name
,x.n.value('@country', 'VARCHAR(5)') as RateCountry
,x.n.value('@value', 'DECIMAL(10,4)') as Rate
FROM xCTE
CROSS APPLY DocXml.nodes('/Data/FuelType') x(n)
基本思想:在CTE中使用XQuery将原始文档转换为更易于管理的内容 - 获取当前FUEL_TYPE
节点之前的最后一个RATE
节点,并将所有内容填充到单个XML元素中(或元素组 - 属性更紧凑,更容易使用IMO)。
这并没有给你想要的输出 - 它提供了这样的输出:
Jurisdiction Country Name RateCountry Rate
------------ ------- -------------------- ----------- ---------------------------------------
AB CAN Gasoline US 0.3734
AB CAN Gasoline CAN 0.1300
AB CAN Special Diesel US 0.3734
AB CAN Special Diesel CAN 0.1300
...
如果你想从那里出发,你应该可以做某种CROSS APPLY
或PIVOT
,但在我走这条路之前,我会考虑是否会这样做&{0}} #39; s 真的你想要什么,或者这实际上会更好。
答案 1 :(得分:3)
这是另一种解决方案,可能会更容易一些。这个想法与Dan的方法大致相同(这很棒!)。
差异:我使用Configuration
获取所有APPLY .nodes()
个节点,并查找他们的上一个 <RATE>
*。
<FUEL_TYPE>
结果的第一行:
SELECT @xml.value(N'(/RECORD/JURISDICTION/@ID)[1]',N'nvarchar(max)') AS JURISDICTION_ID
,@xml.value(N'(/RECORD/JURISDICTION/text())[1]',N'nvarchar(max)') AS JURISDICTION
,@xml.value(N'(/RECORD/COUNTRY/text())[1]',N'nvarchar(max)') AS COUNTRY
,r.value(N'let $r:=. return ../FUEL_TYPE[.<<$r][last()]',N'varchar(max)') AS FUEL_TYPE
,r.value(N'(./@COUNTRY)[1]',N'nvarchar(max)') AS RATE_COUNTRY
,r.value(N'(./@RATECHANGE)[1]',N'int') AS RATE_RATECHANGE
,r.value(N'(./text())[1]',N'decimal(8,4)') AS RATE
FROM @xml.nodes(N'/RECORD/RATE') AS A(r)
这种暴力方法怎么样?
+-----------------+--------------+---------+----------------+--------------+-----------------+--------+
| JURISDICTION_ID | JURISDICTION | COUNTRY | FUEL_TYPE | RATE_COUNTRY | RATE_RATECHANGE | RATE |
+-----------------+--------------+---------+----------------+--------------+-----------------+--------+
| #15 | AB | CAN | Gasoline | US | 0 | 0.3734 |
+-----------------+--------------+---------+----------------+--------------+-----------------+--------+
| #15 | AB | CAN | Gasoline | CAN | 0 | 0.1300 |
+-----------------+--------------+---------+----------------+--------------+-----------------+--------+
| #15 | AB | CAN | Special Diesel | US | 0 | 0.3734 |
+-----------------+--------------+---------+----------------+--------------+-----------------+--------+
| #15 | AB | CAN | Special Diesel | CAN | 0 | 0.1300 |
+-----------------+--------------+---------+----------------+--------------+-----------------+--------+
| #15 | AB | CAN | Gasohol | US | 0 | 0.3734 |