解析C#中的CSS:解压缩所有URL

前端之家收集整理的这篇文章主要介绍了解析C#中的CSS:解压缩所有URL前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要从CSS文件获取所有URL(url()表达式).例如:
b { background: url(img0) }
b { background: url("img1") }
b { background: url('img2') }
b { background: url( img3 ) }
b { background: url( "img4" ) }
b { background: url( 'img5' ) }
b { background: url (img6) }
b { background: url ("img7") }
b { background: url ('img8') }
{ background: url('noimg0) }
{ background: url(noimg1') }
/*b { background: url(noimg2) }*/
b { color: url(noimg3) }
b { content: 'url(noimg4)' }
@media screen and (max-width: 1280px) { b { background: url(img9) } }
b { background: url(img10) }

我需要获取所有的img * URL,而不是noimg * URL(无效的语法或无效的属性或内部注释).

我试过使用好的旧正则表达式.经过一番试错,我得到了:

private static IEnumerable<string> ParseUrlsRegex (string source)
{
    var reUrls = new Regex(@"(?nx)
        url \s* \( \s*
            (
                (?! ['""] )
                (?<Url> [^\)]+ )
                (?<! ['""] )
                |
                (?<Quote> ['""] )
                (?<Url> .+? )
                \k<Quote>
            )
        \s* \)");
    return reUrls.Matches(source)
        .Cast<Match>()
        .Select(match => match.Groups["Url"].Value);
}

这是一个疯狂的正则表达式,但它仍然不起作用 – 它匹配3个无效URL(即2,3和4).此外,每个人都会说,使用正则表达式来解析复杂的语法是错误的.

我们来试试另一种方法.根据this question,唯一可行的选择是ExCSS(其他可能太简单或过时).有了ExCSS,我得到了:

private static IEnumerable<string> ParseUrlsExCss (string source)
    {
        var parser = new StylesheetParser();
        parser.Parse(source);
        return parser.Stylesheet.RuleSets
            .SelectMany(i => i.Declarations)
            .SelectMany(i => i.Expression.Terms)
            .Where(i => i.Type == TermType.Url)
            .Select(i => i.Value);
    }

与正则表达式解决方案不同,它不列出无效的URL.但它没有列出一些有效的!也就是说9和10.看起来像是known issue with some CSS syntax,如果没有从头开始重写整个库,就无法修复它. ANTLR重写似乎是abandoned.

问题:如何从CSS文件提取所有URL? (我需要解析任何CSS文件,不仅仅是上面提供的一个例子,请不要用“noimg”或者假设一行声明.)

注:这不是一个“工具推荐”的问题,因为任何解决方案都将是正常的,无论是一段代码,修复上述解决方案之一,还是其他任何内容;我已经明确定义了我需要的功能.

解决方法

RegEx是一个非常强大的工具.但是,当需要更多的灵活性时,我更喜欢写一点代码.

所以对于非RegEx解决方案,我想出了以下几点.请注意,需要更多的工作来使此代码更通用来处理任何CSS文件.为此,我也将使用我的text parsing helper class.

IEnumerable<string> GetUrls(string css)
{
    char[] trimChars = new char[] { '\'','"',' ','\t',};

    foreach (var line in css.Split(new string[] { Environment.NewLine },StringSplitOptions.RemoveEmptyEntries))
    {
        // Extract portion within curly braces (this version assumes all on one line)
        int start = line.IndexOf('{');
        int end = line.IndexOf('}',start + 1);
        if (start < 0 || end < 0)
            continue;
        start++; end--; // Remove braces

        // Get value portion
        start = line.IndexOf(':',start);
        if (start < 0)
            continue;

        // Extract value and trime whitespace and quotes
        string content = line.Substring(start + 1,end - start).Trim(trimChars);

        // Extract URL from url() value
        if (!content.StartsWith("url",StringComparison.InvariantCultureIgnoreCase))
            continue;
        start = content.IndexOf('(');
        end = content.IndexOf(')',start + 1);
        if (start < 0 || end < 0)
            continue;
        start++;
        content = content.Substring(start,end - start).Trim(trimChars);

        if (!content.StartsWith("noimg",StringComparison.InvariantCultureIgnoreCase))
            yield return content;
    }
}

更新:

你似乎在问的似乎超出了一个简单的问题stackoverflow的范围.我不相信你会使用正则表达式获得令人满意的结果.您将需要一些代码来解析您的CSS,并处理所有特殊情况.

由于我写了很多解析代码,并且有一段时间,所以我决定玩这个.我写了一个简单的CSS解析器,并写了一篇关于它的文章.您可以在A Simple CSS Parser阅读文章并下载代码(免费).

我的代码解析一个CSS块,并将信息存储在数据结构中.我的代码分隔并存储每个规则的每个属性/值对.但是,从属性获取URL还需要更多的工作.您将需要从属性值解析它们.

我最初发布的代码将会让您开始了解如何处理此问题.但是,如果您想要一个真正强大的解决方案,那么将需要一些更复杂的代码.你可能想看看我的代码来解析CSS.我使用该代码中的技术,可以用于轻松处理诸如url(‘img(1)’)的值,例如解析引用的值.

我认为这是一个很好的开始.我也可以为你编写剩余的代码.但那是什么乐趣呢?

猜你在找的C#相关文章