ホワイトリストにないHTMLアジリティパックストリップタグ


質問

私はHTMLタグとホワイトリストにない属性を削除する関数を作成しようとしています。私は次のHTMLを持っています:

<b>first text </b>
<b>second text here
       <a>some text here</a>
 <a>some text here</a>

 </b>
<a>some twxt here</a>

私はHTMLの敏捷性パックを使用しており、これまでのコードは次のとおりです。

<b>first text </b>
<b>second text here
       <a>some text here</a>
 <a>some text here</a>

 </b>
<a>some twxt here</a>

私が達成しようとしている出力は

<b>first text </b>
<b>second text here
       <a>some text here</a>
 <a>some text here</a>

 </b>
<a>some twxt here</a>

つまり、私は<b>タグを保持したいだけです。
私はこれをやっている理由は、ユーザーの中にはMS WORDからNy WYSYWYG htmlエディタにcpoy-pasteを実行する人がいるからです。

ありがとう!

受け入れられた回答

heh、明らかに私は誰かが作ったブログ投稿で答えを見つけた。

using System.Collections.Generic;
using System.Linq;
using HtmlAgilityPack;

namespace Wayloop.Blog.Core.Markup
{
    public static class HtmlSanitizer
    {
        private static readonly IDictionary<string, string[]> Whitelist;

        static HtmlSanitizer()
        {
            Whitelist = new Dictionary<string, string[]> {
                { "a", new[] { "href" } },
                { "strong", null },
                { "em", null },
                { "blockquote", null },
                };
        }

        public static string Sanitize(string input)
        {
            var htmlDocument = new HtmlDocument();

            htmlDocument.LoadHtml(input);
            SanitizeNode(htmlDocument.DocumentNode);

            return htmlDocument.DocumentNode.WriteTo().Trim();
        }

        private static void SanitizeChildren(HtmlNode parentNode)
        {
            for (int i = parentNode.ChildNodes.Count - 1; i >= 0; i--) {
                SanitizeNode(parentNode.ChildNodes[i]);
            }
        }

        private static void SanitizeNode(HtmlNode node)
        {
            if (node.NodeType == HtmlNodeType.Element) {
                if (!Whitelist.ContainsKey(node.Name)) {
                    node.ParentNode.RemoveChild(node);
                    return;
                }

                if (node.HasAttributes) {
                    for (int i = node.Attributes.Count - 1; i >= 0; i--) {
                        HtmlAttribute currentAttribute = node.Attributes[i];
                        string[] allowedAttributes = Whitelist[node.Name];
                        if (!allowedAttributes.Contains(currentAttribute.Name)) {
                            node.Attributes.Remove(currentAttribute);
                        }
                    }
                }
            }

            if (node.HasChildNodes) {
                SanitizeChildren(node);
            }
        }
    }
}

私はここからHtmlSanitizerを取得しています明らかにそれはタグを削除しませんが、要素を削除します。

OK、後で必要とする人のためのソリューションです。

using System.Collections.Generic;
using System.Linq;
using HtmlAgilityPack;

namespace Wayloop.Blog.Core.Markup
{
    public static class HtmlSanitizer
    {
        private static readonly IDictionary<string, string[]> Whitelist;

        static HtmlSanitizer()
        {
            Whitelist = new Dictionary<string, string[]> {
                { "a", new[] { "href" } },
                { "strong", null },
                { "em", null },
                { "blockquote", null },
                };
        }

        public static string Sanitize(string input)
        {
            var htmlDocument = new HtmlDocument();

            htmlDocument.LoadHtml(input);
            SanitizeNode(htmlDocument.DocumentNode);

            return htmlDocument.DocumentNode.WriteTo().Trim();
        }

        private static void SanitizeChildren(HtmlNode parentNode)
        {
            for (int i = parentNode.ChildNodes.Count - 1; i >= 0; i--) {
                SanitizeNode(parentNode.ChildNodes[i]);
            }
        }

        private static void SanitizeNode(HtmlNode node)
        {
            if (node.NodeType == HtmlNodeType.Element) {
                if (!Whitelist.ContainsKey(node.Name)) {
                    node.ParentNode.RemoveChild(node);
                    return;
                }

                if (node.HasAttributes) {
                    for (int i = node.Attributes.Count - 1; i >= 0; i--) {
                        HtmlAttribute currentAttribute = node.Attributes[i];
                        string[] allowedAttributes = Whitelist[node.Name];
                        if (!allowedAttributes.Contains(currentAttribute.Name)) {
                            node.Attributes.Remove(currentAttribute);
                        }
                    }
                }
            }

            if (node.HasChildNodes) {
                SanitizeChildren(node);
            }
        }
    }
}

XML名前空間ノードを解析する必要があれば、xpath解析でクラッシュするので、ノードの名前を変更しました。


人気のある回答

コードをありがとう - 素晴らしいこと!!!!

私はいくつかの最適化を行った...

class TagSanitizer
{
    List<HtmlNode> _deleteNodes = new List<HtmlNode>();

    public static void Sanitize(HtmlNode node)
    {
        new TagSanitizer().Clean(node);
    }

    void Clean(HtmlNode node)
    {
        CleanRecursive(node);
        for (int i = _deleteNodes.Count - 1; i >= 0; i--)
        {
            HtmlNode nodeToDelete = _deleteNodes[i];
            nodeToDelete.ParentNode.RemoveChild(nodeToDelete, true);
        }
    }

    void CleanRecursive(HtmlNode node)
    {
        if (node.NodeType == HtmlNodeType.Element)
        {
            if (Config.TagsWhiteList.ContainsKey(node.Name) == false)
            {
                _deleteNodes.Add(node);
            }
            else if (node.HasAttributes)
            {
                for (int i = node.Attributes.Count - 1; i >= 0; i--)
                {
                    HtmlAttribute currentAttribute = node.Attributes[i];

                    string[] allowedAttributes = Config.TagsWhiteList[node.Name];
                    if (allowedAttributes != null)
                    {
                        if (allowedAttributes.Contains(currentAttribute.Name) == false)
                        {
                            node.Attributes.Remove(currentAttribute);
                        }
                    }
                    else
                    {
                        node.Attributes.Remove(currentAttribute);
                    }
                }
            }
        }

        if (node.HasChildNodes)
        {
            node.ChildNodes.ToList().ForEach(v => CleanRecursive(v));
        }
    }
}




ライセンスを受けた: CC-BY-SA
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ