sql - 使用 Oracle 解析 HTML 表
问题描述
我需要解析一个 HTML 表格:
<table>
<tbody>
<tr class="blue"><td>code</td><td>rate</td></tr>
<tr class="gray_1"><td><span>USD</span><em>1</em></td><td>476.16</td></tr>
<tr class="gray_2"><td><span>AUD</span><em>1</em></td><td>327.65</td></tr>
<tr class="gray_9"><td><span>IRR</span><em>100</em></td><td>1.13</td></tr>
<tr class="blue"><td>some comment</td><td>some comment</td></tr>
<tr class="gray_1"><td><span>EUR</span><em>1</em></td><td>526.54</td></tr>
</tbody>
</table>
结果得到:
+------+----+----+------+
|class |code|em |value |
+------+----+----+------+
|gray_1|USD | 1| 11.11|
|gray_2|AUD | 1| 22.22|
|gray_9|IRR | 100| 33.33|
|gray_1|EUR | 1| 44.44|
我试着这样做:
with tbl as
(
select xmltype('
<table>
<tbody>
<tr class="blue"><td>code</td><td>rate</td></tr>
<tr class="gray_1"><td><span>USD</span><em>1</em></td><td>476.16</td></tr>
<tr class="gray_2"><td><span>AUD</span><em>1</em></td><td>327.65</td></tr>
<tr class="gray_9"><td><span>IRR</span><em>100</em></td><td>1.13</td></tr>
<tr class="blue"><td>some comment</td><td>some comment</td></tr>
<tr class="gray_1"><td><span>EUR</span><em>1</em></td><td>526.54</td></tr>
</tbody>
</table>
') xml_data from dual
)
select
*
from
tbl,
xmltable('//table/tbody/tr'
passing tbl.xml_data
columns
data varchar2(128) path './td'
)
但这会导致异常:
ORA-19279: XPTY0004 - XQuery 动态类型不匹配:预期的单例序列 - 得到多项目序列
我需要做什么来修复我的代码?
解决方案
您正在path
寻找; 但是有两个,因此您会看到“得到多项序列”错误。您可以通过每个标签的位置等来引用每个标签。它非常依赖于表结构是否符合预期。td
tr
td
td[1]
使用这个特定示例,您可以执行以下操作:
with tbl as
(
select xmltype('
<table>
<tbody>
<tr class="blue"><td>code</td><td>rate</td></tr>
<tr class="gray_1"><td><span>USD</span><em>1</em></td><td>476.16</td></tr>
<tr class="gray_2"><td><span>AUD</span><em>1</em></td><td>327.65</td></tr>
<tr class="gray_9"><td><span>IRR</span><em>100</em></td><td>1.13</td></tr>
<tr class="blue"><td>some comment</td><td>some comment</td></tr>
<tr class="gray_1"><td><span>EUR</span><em>1</em></td><td>526.54</td></tr>
</tbody>
</table>
') xml_data from dual
)
select
x.class, x.currency, x.amount, to_number(x.rate) as rate
from
tbl
cross join
xmltable('/table/tbody/tr'
passing tbl.xml_data
columns
class varchar2(10) path '@class',
currency varchar2(3) path 'td[1]/span',
amount number path 'td[1]/em',
rate varchar2(50) path 'td[2]'
) x
where
x.currency is not null
得到:
CLASS CUR AMOUNT RATE
---------- --- ---------- ----------
gray_1 USD 1 476.16
gray_2 AUD 1 327.65
gray_9 IRR 100 1.13
gray_1 EUR 1 526.54
不过,它不需要太多的 HTML 变化来破坏它。由于某些原因,它很脆弱,以及为什么通常认为尝试将 HTML 解析为 XML 是不明智的,请参阅此答案。