我遇到了Powershell和MSHTML的问题:getElementById和getElementsByTagName给了我不同的结果。
我有这个HTML文件:
<html>
<head>
<title>Moo</title>
</head>
<body>
<h1>Hello world!</h1>
<ul id="a">
<li>Bob
<li>Cat
<li>Fish
</ul>
<ul id="b">
<li>Bob
<li>Dog
<li>Cow
</ul>
<div id="x">
<b>What's the problem? Don't you <i>like soup</b> like this?</i>.
</div>
</body>
</html>
是的,我故意将其严格嵌套,因为我现在正在玩想法(并测试限制)。
我通过(来自https://stackoverflow.com/a/24989452/130352)将此文件加载到带有MSHTML的Powershell中:
$html = new-object -ComObject "HTMLFile"
$source = get-content -path $htmlFileName -raw
$html.IHtmlDocument2_write($source)
如果我现在这样做:
$d = $html.getElementById("x")
$d.TagName
我得到了预期的输出(DIV
)。但是,如果我这样做:
$d = $html.getElementsByTagName("div")
$d[0].TagName
我没有输出。 $d.length
返回1. $d[0] | ft
毫无问题地吐出所有属性和值。但是直接从$ d [0]访问属性并不会返回任何内容(即,请求innerText,outerHtml等返回没有数据,同时按ID查找元素(即使用getElementById
)没有问题我可以访问这些属性。
同样,如果我分配给一个变量(即$z = $d[0]
),然后直接在$ z上工作,我也会遇到同样的问题。
我错过了什么?
答案 0 :(得分:2)
好问题。
无法解释完全发生了什么,但似乎
$d = $html.getElementsByTagName("div")
返回PowerShell不知道如何本机操作的集合。
如果您尝试选择部分(或全部)属性,则变量将完全填充:
($d | select *)[0].tagname
如果使用getElementsByTagName
方法,则可以执行
$d = $html.getElementsByTagName("div") | select *
$d[0].tagname
似乎将ComObject
引导至Select-Object
会导致它被转换为PowerShell PSCustomObject
,然后您就可以使用它了:
[PS]> ($html.getelementsbytagname("div") | select *).gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
[PS]> ($html.getelementsbytagname("div")).gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False __ComObject System.MarshalByRefObject
不是100%肯定这会“回答”这个问题,因为我无法完全解释这种行为,但它至少是一种可行的解决方法