C# C语言中的内联CSS#
我需要从c#中的样式表内联css 就像这样 css很简单,只是类,没有花哨的选择器 我曾考虑使用正则表达式C# C语言中的内联CSS#,c#,css,inlining,C#,Css,Inlining,我需要从c#中的样式表内联css 就像这样 css很简单,只是类,没有花哨的选择器 我曾考虑使用正则表达式(?(?[^{}]+){(?[^{}]+})+从css中去除规则,然后尝试在调用类的地方进行简单的字符串替换,但一些html元素已经有一个样式标记,因此我也必须考虑这一点 有没有更简单的方法?还是已经用c#写的东西 更新-2010年9月16日 我已经能够提出一个简单的CSS内联,只要您的html也是有效的xml。它使用正则表达式获取元素中的所有样式。然后将css选择器转换为xpath表达式
(?(?[^{}]+){(?[^{}]+})+
从css中去除规则,然后尝试在调用类的地方进行简单的字符串替换,但一些html元素已经有一个样式标记,因此我也必须考虑这一点
有没有更简单的方法?还是已经用c#写的东西
更新-2010年9月16日
我已经能够提出一个简单的CSS内联,只要您的html也是有效的xml。它使用正则表达式获取
元素中的所有样式。然后将css选择器转换为xpath表达式,并在任何预先存在的内联样式之前,将内联样式添加到匹配元素中
注意,CssToXpath没有完全实现,有些事情它就是做不到。。。然而
CssInliner.cs
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Xml.XPath;
namespace CssInliner
{
public class CssInliner
{
private static Regex _matchStyles = new Regex("\\s*(?<rule>(?<selector>[^{}]+){(?<style>[^{}]+)})",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
public List<Match> Styles { get; private set; }
public string InlinedXhtml { get; private set; }
private XElement XhtmlDocument { get; set; }
public CssInliner(string xhtml)
{
XhtmlDocument = ParseXhtml(xhtml);
Styles = GetStyleMatches();
foreach (var style in Styles)
{
if (!style.Success)
return;
var cssSelector = style.Groups["selector"].Value.Trim();
var xpathSelector = CssToXpath.Transform(cssSelector);
var cssStyle = style.Groups["style"].Value.Trim();
foreach (var element in XhtmlDocument.XPathSelectElements(xpathSelector))
{
var inlineStyle = element.Attribute("style");
var newInlineStyle = cssStyle + ";";
if (inlineStyle != null && !string.IsNullOrEmpty(inlineStyle.Value))
{
newInlineStyle += inlineStyle.Value;
}
element.SetAttributeValue("style", newInlineStyle.Trim().NormalizeCharacter(';').NormalizeSpace());
}
}
XhtmlDocument.Descendants("style").Remove();
InlinedXhtml = XhtmlDocument.ToString();
}
private List<Match> GetStyleMatches()
{
var styles = new List<Match>();
var styleElements = XhtmlDocument.Descendants("style");
foreach (var styleElement in styleElements)
{
var matches = _matchStyles.Matches(styleElement.Value);
foreach (Match match in matches)
{
styles.Add(match);
}
}
return styles;
}
private static XElement ParseXhtml(string xhtml)
{
return XElement.Parse(xhtml);
}
}
}
还有一些测试
[TestMethod]
public void TestCssToXpathRules()
{
var translations = new Dictionary<string, string>
{
{ "*", "//*" },
{ "p", "//p" },
{ "p > *", "//p/*" },
{ "#foo", "//*[@id='foo']" },
{ "*[title]", "//*[@title]" },
{ ".bar", "//*[contains(concat(' ',normalize-space(@class),' '),' bar ')]" },
{ "div#test .note span:first-child", "//div[@id='test']//*[contains(concat(' ',normalize-space(@class),' '),' note ')]//*[1]/self::span" }
};
foreach (var translation in translations)
{
var expected = translation.Value;
var result = CssInliner.CssToXpath.Transform(translation.Key);
Assert.AreEqual(expected, result);
}
}
[TestMethod]
public void HtmlWithMultiLineClassStyleReturnsInline()
{
#region var html = ...
var html = XElement.Parse(@"<html>
<head>
<title>Hello, World Page!</title>
<style>
.redClass {
background: red;
color: purple;
}
</style>
</head>
<body>
<div class=""redClass"">Hello, World!</div>
</body>
</html>").ToString();
#endregion
#region const string expected ...
var expected = XElement.Parse(@"<html>
<head>
<title>Hello, World Page!</title>
</head>
<body>
<div class=""redClass"" style=""background: red; color: purple;"">Hello, World!</div>
</body>
</html>").ToString();
#endregion
var result = new CssInliner.CssInliner(html);
Assert.AreEqual(expected, result.InlinedXhtml);
}
好问题
我不知道是否有.NET解决方案,但我发现了一个名为的Ruby程序,它声称可以内联CSS。如果你想使用它,你有几个选择:
这里有一个想法,你为什么不打个电话来使用c。从使用firebug的分析来看,post调用似乎需要两个参数html和strip,它们取值(开/关),结果是一个名为text的参数
下面是一个关于如何创建一个Chad的示例,您是否必须添加CSS内联?或者在
中添加一个
块会更好吗?这将在本质上取代对CSS文件引用的需要,并维护实际内联规则覆盖头/引用CSS文件中设置的规则
(对不起,忘记添加代码的引号了)我推荐这样的口述:
private Dictionary<string, Dictionary<string, string>> cssDictionary = new Dictionary<string, Dictionary<string, string>();
private Dictionary cssDictionary=new Dictionary既然您的当前实现已经完成了90%的工作,为什么不使用现有的框架,而用HTML解析器代替XML解析呢?其中一个更受欢迎的是。它支持XPath查询,甚至有一个类似于为XML提供的标准.NET接口的LINQ接口,因此它应该是一个相当简单的替代品。我建议使用实际的CSS解析器,而不是正则表达式。您不需要解析完整的语言,因为您主要对复制感兴趣,但在任何情况下都可以使用这样的解析器(对于.NET也是如此)。例如,看看antlr,特别是a或a语法。如果您不介意次优结果(其中内联样式可能包含重复的定义),那么您可能会剥离这两个语法的大部分,但要做到这一点,您需要了解一些内部CSS逻辑,以便能够解析速记属性
但是,从长远来看,这肯定比一系列临时正则表达式修复要少得多。我在Github上有一个项目,它使CSS内联。它非常简单,并且支持移动风格。请在我的博客上阅读更多内容:因为这个选项在其他回复中不是很清楚,我认为它应该得到一个直截了当的回答
使用
你所要做的就是:
通过nuget安装PreMailer.NET
键入以下内容:
var inlineStyles = PreMailer.Net.PreMailer.MoveCssInline(htmlSource, false);
destination = inlineStyles.Html;
你完了
顺便说一句,您可能需要使用
指令添加一个,以缩短该行
当然,在上面的链接中有更多的使用信息。添加了一个悬赏,希望有人已经有东西在里面了。NETI希望你得到一些信息,我不喜欢我的答案。@Greg,这里也是!我正在尝试写一些简单的东西…它不会这么简单…添加了我用于解决方案的代码。请随意改进它。CssToXpath类肯定还可以使用一些增强功能,但它目前符合我的目的。嘿-我刚刚在博客中介绍了我的解决方案,PreMailer.Net:是的,css已经在
元素中,但是BB电子邮件客户端似乎不支持它。但是它确实支持内联样式。CSS内联用于HTML电子邮件有多种原因。主要原因是,许多web电子邮件客户端在将现有样式块包含到自己的html输出之前,会将其从html电子邮件源中剥离出来。但还有Outlook,即使在2019年,它也是一个糟糕的HTML电子邮件客户端,如果不内联CSS样式,你将永远无法驯服它。依赖另一个网站在线、快速且不改变,这个应用程序至关重要。我实际上写了一些类似的东西,效果相当不错。它远非完美无缺,但运行得相当好。我会尝试将其打包并发布到这里。如果我在当前的实现中遇到任何问题,我会对此进行调查。现在,我知道我的“html”是有效的xml,所以xml解析很好,它正在生产中工作。此外,html Agility Pack的解析器甚至不能很好地处理有效的html,例如- x
- y
- z
——它的健壮性不足以处理现实世界的html。请查看此线程()用于讨论其他HTML解析器以及HTML敏捷包。如果它成为一个问题,我可能会这样做。很好。似乎大部分都能工作,但当我使用Zurb“Ink basic template”尝试它时,我得到以下警告:“由于CsQuery中的限制,PreMailer.Net无法处理伪类/元素“a:active”。-我想这取决于CsQuery来解决。顺便说一句,这篇文章说CsQuery现在确实支持它们@MatthewLock是的,正如你链接到的GitHub问题中所描述的,现在有一个问题。亲爱的@MartinHN感谢kind项目,我在使用MoveCssInline时遇到了一个问题,我得到了这个异常(在位置34处发现了意外字符:“…rol solid::>>-@Younisbarznji你能粘贴y吗
private Dictionary<string, Dictionary<string, string>> cssDictionary = new Dictionary<string, Dictionary<string, string>();
Dictionary<string,string> bodyStyleDictionary = new Dictionary<string, string();
bodyStyleDictionary.Add("background", "#000000");
cssDictionary.Add("body", bodyStyleDictionary);
var inlineStyles = PreMailer.Net.PreMailer.MoveCssInline(htmlSource, false);
destination = inlineStyles.Html;