除了使用 Html::Decode 或 RegExps 之外,还有一种更通用的方法可以做到这一点。它要复杂得多,但它可能很有用,当除了链接列之外,某些列包含特殊的 HTML 字符,不应该像链接一样处理(例如 $PageTitle 有类似“foo<bar”的东西,什么会破坏标记使用 Html::Decode 后)。
这种方法使用 ConvertTo-Html 生成有效 XHTML 的事实,可以在 Powershell/.Net XML 工具中使用。主要思想是将 cmdlet 输出转换为 XML 文档,然后使用 XPath 检索链接列并修改它们以使用 DOM 函数创建链接。
这是代码片段:
$pso = New-Object PSObject -Property @{
SiteUrl = 'foobar.org'
PageTitle = 'x&z a<b<c'
PageUrl = 'foobar.org/contact.html'
} | ConvertTo-Html
$xmlDoc = [xml]$pso
$xhtmlNS = 'http://www.w3.org/1999/xhtml'
$xmlNSManager = New-Object System.Xml.XmlNamespaceManager $xmlDoc.NameTable
$xmlNSManager.AddNamespace('x', $xhtmlNS)
$xmlDoc.SelectNodes('//x:table/x:tr/x:td[3]', $xmlNSManager) | %{
$a = $xmlDoc.CreateElement('a', $xhtmlNS)
$a.setAttribute('href', $_.'#text')
[void]$a.AppendChild($xmlDoc.CreateTextNode('Contact Us'))
[void]$_.ReplaceChild($a, $_.FirstChild)
}
$xmlDoc.OuterXml | Out-File 'test.html'
检索第 n 列单元格的 XPath 字符串是 '//x:table/x:tr/x:td[n]',其中 n - 是列数(索引从 1 开始)。可以在此处找到有关使用 XML 命名空间(例如 XmlNamespaceManager 和时髦的 'x:' 前缀)的一些说明:Xml 命名空间破坏了我的 xpath!
要一次修改多个列,可以使用以下 XPath:'//x:table/x:tr/x:td[position()=1 or position()=2 or ... or position()=last( )]'
foreach ($td in $xmlDoc.SelectNodes('//x:table/x:tr/x:td[position()=1 or position()=2 or ... or position()=last()]', $xmlNSManager)) {
# processing first column cells
[void]$foreach.MoveNext()
# processing second column cells
[void]$foreach.MoveNext()
# etc
}