在PowerShell中解析HTML实体

5
我正在使用PowerShell通过Microsoft Team Foundation Server。我想要完成的任务是获取并设置特定工作项(类型为“测试用例”)的“步骤”。
出于我不知道的原因,TFS将此类信息存储为XML中的HTML,其中HTML元素使用HTML实体编写,以免与XML混淆。
以下是一个示例:
<steps id="0" last="3">
    <step id="2" type="ValidateStep">
        <parameterizedString isformatted="true">
            &lt;DIV&gt;&lt;P&gt;I do this and that&lt;/P&gt;&lt;/DIV&gt;
        </parameterizedString>
        <parameterizedString isformatted="true">
            &lt;DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;
        </parameterizedString>
        <description/>
    </step>
    <step id="3" type="ActionStep">
        <parameterizedString isformatted="true">
            &lt;DIV&gt;&lt;DIV&gt;&lt;P&gt;I do something else &lt;BR/&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;
        </parameterizedString>
        <parameterizedString isformatted="true">
            &lt;DIV&gt;&lt;P&gt;This happens &lt;BR/&gt;&lt;/P&gt;&lt;/DIV&gt;
        </parameterizedString>
        <description/>
    </step>
</steps>

看起来是这样的: TFS如何呈现测试用例步骤的屏幕截图

如何获取每个项目的“裸文本”?例如,This happens 是由 &lt;DIV&gt;&lt;P&gt;This happens &lt;BR/&gt;&lt;/P&gt;&lt;/DIV&gt; 生成的。 我必须编写自己的解析器或者有现成的工具可以使用吗?

1个回答

9

System.Web 命名空间中有一个可以帮助您的东西:

PS> add-type -AssemblyName system.web
PS> [System.Web.HttpUtility]::HtmlDecode("Baskin &amp; Robbins")
Baskin & Robbins

更新

我再次阅读了你的问题,发现你需要更多的东西。如果你不熟悉xml和html语义,这有点棘手,所以我为你准备了一份脚本。希望你可以根据自己的需求进行修改。

add-type -AssemblyName system.web

$raw = @'
<steps id="0" last="3">
    <step id="2" type="ValidateStep">
        <parameterizedString isformatted="true">
            &lt;DIV&gt;&lt;P&gt;I do this and that&lt;/P&gt;&lt;/DIV&gt;
        </parameterizedString>
        <parameterizedString isformatted="true">
            &lt;DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;
        </parameterizedString>
        <description/>
    </step>
    <step id="3" type="ActionStep">
        <parameterizedString isformatted="true">
            &lt;DIV&gt;&lt;DIV&gt;&lt;P&gt;I do something else &lt;BR/&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;
        </parameterizedString>
        <parameterizedString isformatted="true">
            &lt;DIV&gt;&lt;P&gt;This happens &lt;BR/&gt;&lt;/P&gt;&lt;/DIV&gt;
        </parameterizedString>
        <description/>
    </step>
</steps>
'@

$xml = [xml]$raw

$xml.steps.step | foreach-object { 
  write-host ('Processing {0}...' -f $_.type)

  $_.parameterizedString | foreach-object {
    # decode html entities
    $html = [System.Web.HttpUtility]::HtmlDecode($_.innerText)

    # let's hope the html is balanced and valid xhtml (matching begin/end tags)
    # assumption is that the innermost <P> wraps the desired text
    # match with xpath
    $text = ([xml]$html).SelectSingleNode('//P/text()').value

    write-host "Text: '$text'"
  }
}

太棒了。由于我也对“设置”这些字段(以编程方式编写测试用例)感兴趣,发现有一个补充方法叫做HtmlEncode真是个惊喜。 - Jir
1
当您像这样使用XML解析器时,无需解码实体。 $_.innerText已经检索到解码的字符串,因此HtmlDecode()是多余的。 - zett42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接