using System; using System.Xml; using System.Xml.XPath; using System.Text.RegularExpressions; using SharpVectors.Dom.Stylesheets; using System.Collections; using System.Collections.Generic; namespace SharpVectors.Dom.Css { /// /// The CSSStyleRule interface represents a single rule set in a CSS style sheet. /// /// niklas@protocol7.com /// 80 public class CssStyleRule : CssRule,ICssStyleRule { #region Static members internal static string nsPattern = @"([A-Za-z\*][A-Za-z0-9]*)?\|"; internal static string attributeValueCheck = "(?(" + nsPattern + ")?[a-zA-Z0-9]+)\\s*(?[\\~\\^\\$\\*\\|]?)=\\s*(\"|\')?(?.*?)(\"|\')?"; internal static string sSelector = "(?" + nsPattern + ")?" + @"(?([A-Za-z\*][A-Za-z0-9]*))?" + @"((?\.[A-Za-z][A-Za-z0-9]*)+)?" + @"(?\#[A-Za-z][A-Za-z0-9]*)?" + @"((?\[\s*(" + @"(?(" + nsPattern + ")?[a-zA-Z0-9]+)" + @"|" + "(?" + attributeValueCheck + ")" + @")\s*\])+)?" + @"((?\:[a-z\-]+(\([^\)]+\))?)+)?" + @"(?(\:\:[a-z\-]+)+)?" + @"(?(\s*(\+|\>|\~)\s*)|(\s+))?"; private static string sStyleRule = "^((?(" + sSelector + @")+)(\s*,\s*)?)+"; private static Regex regex = new Regex(sStyleRule); internal static CssRule Parse(ref string css, object parent, bool readOnly, IList replacedStrings, CssStyleSheetType origin) { Match match = regex.Match(css); if(match.Success && match.Length > 0) { CssStyleRule rule = new CssStyleRule(match, parent, readOnly, replacedStrings, origin); css = css.Substring(match.Length); rule._Style = new CssStyleDeclaration(ref css, rule, readOnly, origin); return rule; } else { return null; } } #endregion #region Constructors /// /// The constructor for CssStyleRule /// /// The Regex match that found the charset rule /// The parent rule or parent stylesheet /// True if this instance is readonly /// An array of strings that have been replaced in the string used for matching. These needs to be put back use the DereplaceStrings method /// The type of CssStyleSheet internal CssStyleRule(Match match, object parent, bool readOnly, IList replacedStrings, CssStyleSheetType origin) : base(parent, readOnly, replacedStrings, origin) { //SelectorText = DeReplaceStrings(match.Groups["selectors"].Value.Trim()); //_Style = new CssStyleDeclaration(match, this, readOnly, Origin); Group selectorMatches = match.Groups["selector"]; int len = selectorMatches.Captures.Count; ArrayList sels = new ArrayList(); for(int i = 0; i 0) { sels.Add(new CssXPathSelector(str)); } } XPathSelectors = (CssXPathSelector[])sels.ToArray(typeof(CssXPathSelector)); } #endregion #region Public methods /// /// Used to find matching style rules in the cascading order /// /// The element to find styles for /// The pseudo-element to find styles for /// The medialist that the document is using /// A CssStyleDeclaration that holds the collected styles protected internal override void GetStylesForElement(XmlElement elt, string pseudoElt, MediaList ml, CssCollectedStyleDeclaration csd) { XPathNavigator nav = elt.CreateNavigator(); foreach(CssXPathSelector sel in XPathSelectors) { // TODO: deal with pseudoElt if(sel != null && sel.Matches(nav)) { ((CssStyleDeclaration)Style).GetStylesForElement(csd, sel.Specificity); break; } } } #endregion #region Private fields private CssXPathSelector[] XPathSelectors; #endregion #region Implementation of ICssStyleRule /// /// The textual representation of the selector for the rule set. The implementation may have stripped out insignificant whitespace while parsing the selector. /// /// SYNTAX_ERR: Raised if the specified CSS string value has a syntax error and is unparsable. /// NO_MODIFICATION_ALLOWED_ERR: Raised if this rule is readonly public string SelectorText { get { string ret = String.Empty; foreach(CssXPathSelector sel in XPathSelectors) { ret += sel.CssSelector + ","; } return ret.Substring(0, ret.Length-1); } set { // TODO: invalidate throw new NotImplementedException("setting SelectorText"); } } /// /// The entire text of the CssStyleRule /// public override string CssText { get { return SelectorText + "{" + ((CssStyleDeclaration)Style).CssText + "}"; } } private CssStyleDeclaration _Style; /// /// The declaration-block of this rule set. /// public ICssStyleDeclaration Style { get { return _Style; } } #endregion #region Implementation of ICssRule /// /// The type of the rule. The expectation is that binding-specific casting methods can be used to cast down from an instance of the CSSRule interface to the specific derived interface implied by the type. /// public override CssRuleType Type { get { return CssRuleType.StyleRule; } } #endregion } }