この質問を興味深いものにしているのは、HTML が XML と同じように見えて匂いがすることです。理想的な世界では HTML は XML のサブセットですが、実際の HTML は明らかにXML ではありません。質問の例を任意の XML パーサーに入力すると、さまざまな違反が発生します。そうは言っても、1 行の PowerShell で目的の結果を得ることができます。これは、href のテキスト全体を返します。
Select-NodeContent $doc.DocumentNode "//a/@href"
そして、これは目的の部分文字列を抽出します:
Select-NodeContent $doc.DocumentNode "//a/@href" "IP_PHONE_BACKUP-(.*)\.zip"
ただし、問題は、その 1 行のコードを実行できるようにするためのオーバーヘッド/セットアップにあります。必要がある:
これらの要件が満たされると、HTMLAgilityPath
型を環境に追加し、Select-NodeContent
関数を定義できます。両方を以下に示します。$doc
コードの最後は、上記のワンライナーで使用される変数に値を割り当てる方法を示しています。必要に応じて、ファイルまたは Web から HTML をロードする方法を示します。
Set-StrictMode -Version Latest
$HtmlAgilityPackPath = [System.IO.Path]::Combine((Get-Item $PROFILE).DirectoryName, "bin\HtmlAgilityPack.dll")
Add-Type -Path $HtmlAgilityPackPath
function Select-NodeContent(
[HtmlAgilityPack.HtmlNode]$node,
[string] $xpath,
[string] $regex,
[Object] $default = "")
{
if ($xpath -match "(.*)/@(\w+)$") {
# If standard XPath to retrieve an attribute is given,
# map to supported operations to retrieve the attribute's text.
($xpath, $attribute) = $matches[1], $matches[2]
$resultNode = $node.SelectSingleNode($xpath)
$text = ?: { $resultNode } { $resultNode.Attributes[$attribute].Value } { $default }
}
else { # retrieve an element's text
$resultNode = $node.SelectSingleNode($xpath)
$text = ?: { $resultNode } { $resultNode.InnerText } { $default }
}
# If a regex is given, use it to extract a substring from the text
if ($regex) {
if ($text -match $regex) { $text = $matches[1] }
else { $text = $default }
}
return $text
}
$doc = New-Object HtmlAgilityPack.HtmlDocument
$result = $doc.Load("tmp\temp.html") # Use this to load a file
#$result = $doc.LoadHtml((Get-HttpResource $url)) # Use this PSCX cmdlet to load a live web page