Powershell中getElementById和getElementsByName之间的差异

时间:2015-01-07 13:50:01

标签: powershell dom

我遇到了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上工作,我也会遇到同样的问题。

我错过了什么?

1 个答案:

答案 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%肯定这会“回答”这个问题,因为我无法完全解释这种行为,但它至少是一种可行的解决方法