18

私はこのようなhtml文字列を持っています:

<html><body><p>foo <a href='http://www.example.com'>bar</a> baz</p></body></html>

結果の文字列が次のようになるように、すべてのhtmlタグを削除したいと思います。

foo bar baz

SOの別の投稿から、この関数(Html Agility Packを使用)を思いつきました。

  Public Shared Function stripTags(ByVal html As String) As String
    Dim plain As String = String.Empty
    Dim htmldoc As New HtmlAgilityPack.HtmlDocument

    htmldoc.LoadHtml(html)
    Dim invalidNodes As HtmlAgilityPack.HtmlNodeCollection = htmldoc.DocumentNode.SelectNodes("//html|//body|//p|//a")

    If Not htmldoc Is Nothing Then
      For Each node In invalidNodes
        node.ParentNode.RemoveChild(node, True)
      Next
    End If

    Return htmldoc.DocumentNode.WriteContentTo
  End Function

残念ながら、これは私が期待するものを返しません、代わりにそれは与えます:

bazbarfoo

どうか、どこが間違っているのですか?これが最善のアプローチですか?

よろしくと幸せなコーディング!

更新:以下の答えによって、私はこの関数を思いついた、他の人に役立つかもしれない:

  Public Shared Function stripTags(ByVal html As String) As String
    Dim htmldoc As New HtmlAgilityPack.HtmlDocument
    htmldoc.LoadHtml(html.Replace("</p>", "</p>" & New String(Environment.NewLine, 2)).Replace("<br/>", Environment.NewLine))
    Return htmldoc.DocumentNode.InnerText
  End Function
4

5 に答える 5

33

htmldoc.DocumentNode.InnerTextすべての非テキストノードを削除するのではなく、単に戻るのはなぜですか?それはあなたが望むものをあなたに与えるはずです。

于 2010-06-29T13:19:12.390 に答える
2

ホワイトリストにないタグとプロパティを削除します。

Public NotInheritable Class HtmlSanitizer
    Private Sub New()
    End Sub
    Private Shared ReadOnly Whitelist As IDictionary(Of String, String())
    Private Shared DeletableNodesXpath As New List(Of String)()

    Shared Sub New()
        Whitelist = New Dictionary(Of String, String())() From { _
            {"a", New () {"href"}}, _
            {"strong", Nothing}, _
            {"em", Nothing}, _
            {"blockquote", Nothing}, _
            {"b", Nothing}, _
            {"p", Nothing}, _
            {"ul", Nothing}, _
            {"ol", Nothing}, _
            {"li", Nothing}, _
            {"div", New () {"align"}}, _
            {"strike", Nothing}, _
            {"u", Nothing}, _
            {"sub", Nothing}, _
            {"sup", Nothing}, _
            {"table", Nothing}, _
            {"tr", Nothing}, _
            {"td", Nothing}, _
            {"th", Nothing} _
        }
    End Sub

    Public Shared Function Sanitize(input As String) As String
        If input.Trim().Length < 1 Then
            Return String.Empty
        End If
        Dim htmlDocument = New HtmlDocument()

        htmlDocument.LoadHtml(input)
        SanitizeNode(htmlDocument.DocumentNode)
        Dim xPath As String = HtmlSanitizer.CreateXPath()

        Return StripHtml(htmlDocument.DocumentNode.WriteTo().Trim(), xPath)
    End Function

    Private Shared Sub SanitizeChildren(parentNode As HtmlNode)
        For i As Integer = parentNode.ChildNodes.Count - 1 To 0 Step -1
            SanitizeNode(parentNode.ChildNodes(i))
        Next
    End Sub

    Private Shared Sub SanitizeNode(node As HtmlNode)
        If node.NodeType = HtmlNodeType.Element Then
            If Not Whitelist.ContainsKey(node.Name) Then
                If Not DeletableNodesXpath.Contains(node.Name) Then
                    'DeletableNodesXpath.Add(node.Name.Replace("?",""));
                    node.Name = "removeableNode"
                    DeletableNodesXpath.Add(node.Name)
                End If
                If node.HasChildNodes Then
                    SanitizeChildren(node)
                End If

                Return
            End If

            If node.HasAttributes Then
                For i As Integer = node.Attributes.Count - 1 To 0 Step -1
                    Dim currentAttribute As HtmlAttribute = node.Attributes(i)
                    Dim allowedAttributes As String() = Whitelist(node.Name)
                    If allowedAttributes IsNot Nothing Then
                        If Not allowedAttributes.Contains(currentAttribute.Name) Then
                            node.Attributes.Remove(currentAttribute)
                        End If
                    Else
                        node.Attributes.Remove(currentAttribute)
                    End If
                Next
            End If
        End If

        If node.HasChildNodes Then
            SanitizeChildren(node)
        End If
    End Sub

    Private Shared Function StripHtml(html As String, xPath As String) As String
        Dim htmlDoc As New HtmlDocument()
        htmlDoc.LoadHtml(html)
        If xPath.Length > 0 Then
            Dim invalidNodes As HtmlNodeCollection = htmlDoc.DocumentNode.SelectNodes(xPath)
            For Each node As HtmlNode In invalidNodes
                node.ParentNode.RemoveChild(node, True)
            Next
        End If
        Return htmlDoc.DocumentNode.WriteContentTo()


    End Function

    Private Shared Function CreateXPath() As String
        Dim _xPath As String = String.Empty
        For i As Integer = 0 To DeletableNodesXpath.Count - 1
            If i IsNot DeletableNodesXpath.Count - 1 Then
                _xPath += String.Format("//{0}|", DeletableNodesXpath(i).ToString())
            Else
                _xPath += String.Format("//{0}", DeletableNodesXpath(i).ToString())
            End If
        Next
        Return _xPath
    End Function
End Class
于 2010-08-29T19:55:00.737 に答える
1

ForEachがドキュメントを最初から最後までトラバースすると想定しているようです。それを確実に実行したい場合は、通常のforループを使用してください。xpathセレクターを使用して、ノードが期待どおりの順序でピックアップされていることを確認することもできませんが、この場合は正しい可能性があります。

よろしく、ブルーニス

于 2011-02-08T13:13:40.433 に答える
0

以下の数行を編集すると、必要なものが得られます。

Private Shared Function StripHtml(html As String, xPath As String) As String
    Dim htmlDoc As New HtmlAgilityPack.HtmlDocument()
    htmlDoc.LoadHtml(html)
    If xPath.Length > 0 Then
        Dim invalidNodes As HtmlNodeCollection = htmlDoc.DocumentNode.SelectNodes(xPath)

        '------- edit this line -------------------
        'For Each node As HtmlNode In invalidNodes
        'node.ParentNode.RemoveChild(node, True)
        'Next
        '
        ' result-> bazbarfoo
        '

        '------- modify line ----------------------
        For i = invalidNodes.Count - 1 To 0 Step -1
            Dim Node As HtmlNode = invalidNodes.Item(i)
            Node.ParentNode.RemoveChild(Node, True)
        Next
        '
        ' result-> foo bar baz
        '
    End If
    Return htmlDoc.DocumentNode.WriteContentTo()


End Function
于 2014-05-05T03:04:16.227 に答える
-6

次のコードを使用できます。

public string RemoveHTMLTags(string source)
{
     string expn = "<.*?>";
     return Regex.Replace(source, expn, string.Empty);
}
于 2010-06-29T13:16:15.400 に答える