/// <summary>
        /// Init.
        /// </summary>
        public DomParser(CssParser cssParser)
        {
            ArgChecker.AssertArgNotNull(cssParser, "cssParser");

            _cssParser = cssParser;
        }
        /// <summary>
        /// Write the given html tag with all its attributes and styles.
        /// </summary>
        /// <param name="cssParser">used to parse CSS data</param>
        /// <param name="sb">the string builder to write html into</param>
        /// <param name="box">the css box with the html tag to write</param>
        /// <param name="styleGen">Controls the way styles are generated when html is generated</param>
        private static void WriteHtmlTag(CssParser cssParser, StringBuilder sb, CssBox box, HtmlGenerationStyle styleGen)
        {
            sb.AppendFormat("<{0}", box.HtmlTag.Name);

            // collect all element style properties including from stylesheet
            var tagStyles = new Dictionary<string, string>();
            var tagCssBlock = box.HtmlContainer.CssData.GetCssBlock(box.HtmlTag.Name);
            if (tagCssBlock != null)
            {
                // TODO:a handle selectors
                foreach (var cssBlock in tagCssBlock)
                    foreach (var prop in cssBlock.Properties)
                        tagStyles[prop.Key] = prop.Value;
            }

            if (box.HtmlTag.HasAttributes())
            {
                sb.Append(" ");
                foreach (var att in box.HtmlTag.Attributes)
                {
                    // handle image tags by inserting the image using base64 data
                    if (styleGen == HtmlGenerationStyle.Inline && att.Key == HtmlConstants.Style)
                    {
                        // if inline style add the styles to the collection
                        var block = cssParser.ParseCssBlock(box.HtmlTag.Name, box.HtmlTag.TryGetAttribute("style"));
                        foreach (var prop in block.Properties)
                            tagStyles[prop.Key] = prop.Value;
                    }
                    else if (styleGen == HtmlGenerationStyle.Inline && att.Key == HtmlConstants.Class)
                    {
                        // if inline style convert the style class to actual properties and add to collection
                        var cssBlocks = box.HtmlContainer.CssData.GetCssBlock("." + att.Value);
                        if (cssBlocks != null)
                        {
                            // TODO:a handle selectors
                            foreach (var cssBlock in cssBlocks)
                                foreach (var prop in cssBlock.Properties)
                                    tagStyles[prop.Key] = prop.Value;
                        }
                    }
                    else
                    {
                        sb.AppendFormat("{0}=\"{1}\" ", att.Key, att.Value);
                    }
                }

                sb.Remove(sb.Length - 1, 1);
            }

            // if inline style insert the style tag with all collected style properties
            if (styleGen == HtmlGenerationStyle.Inline && tagStyles.Count > 0)
            {
                var cleanTagStyles = StripDefaultStyles(box, tagStyles);
                if (cleanTagStyles.Count > 0)
                {
                    sb.Append(" style=\"");
                    foreach (var style in cleanTagStyles)
                        sb.AppendFormat("{0}: {1}; ", style.Key, style.Value);
                    sb.Remove(sb.Length - 1, 1);
                    sb.Append("\"");
                }
            }

            sb.AppendFormat("{0}>", box.HtmlTag.IsSingle ? "/" : "");
        }
 /// <summary>
 /// Parse the given stylesheet to <see cref="CssData"/> object.<br/>
 /// If <paramref name="combineWithDefault"/> is true the parsed css blocks are added to the
 /// default css data (as defined by W3), merged if class name already exists. If false only the data in the given stylesheet is returned.
 /// </summary>
 /// <seealso cref="http://www.w3.org/TR/CSS21/sample.html"/>
 /// <param name="adapter">Platform adapter</param>
 /// <param name="stylesheet">the stylesheet source to parse</param>
 /// <param name="combineWithDefault">true - combine the parsed css data with default css data, false - return only the parsed css data</param>
 /// <returns>the parsed css data</returns>
 public static CssData Parse(RAdapter adapter, string stylesheet, bool combineWithDefault = true)
 {
     CssParser parser = new CssParser(adapter);
     return parser.ParseStyleSheet(stylesheet, combineWithDefault);
 }
        /// <summary>
        /// Write the given html DOM sub-tree into the given string builder.<br/>
        /// If <paramref name="selectedBoxes"/> are given write html only from those tags.
        /// </summary>
        /// <param name="cssParser">used to parse CSS data</param>
        /// <param name="sb">the string builder to write html into</param>
        /// <param name="box">the html sub-tree to write</param>
        /// <param name="styleGen">Controls the way styles are generated when html is generated</param>
        /// <param name="selectedBoxes">Control if to generate only selected boxes, if given only boxes found in hash will be generated</param>
        /// <param name="selectionRoot">the box the is the root of selected boxes (the first box to contain multiple selected boxes)</param>
        private static void WriteHtml(CssParser cssParser, StringBuilder sb, CssBox box, HtmlGenerationStyle styleGen, Dictionary<CssBox, bool> selectedBoxes, CssBox selectionRoot)
        {
            if (box.HtmlTag == null || selectedBoxes == null || selectedBoxes.ContainsKey(box))
            {
                if (box.HtmlTag != null)
                {
                    if (box.HtmlTag.Name != "link" || !box.HtmlTag.Attributes.ContainsKey("href") ||
                        (!box.HtmlTag.Attributes["href"].StartsWith("property") && !box.HtmlTag.Attributes["href"].StartsWith("method")))
                    {
                        WriteHtmlTag(cssParser, sb, box, styleGen);
                        if (box == selectionRoot)
                            sb.Append("<!--StartFragment-->");
                    }

                    if (styleGen == HtmlGenerationStyle.InHeader && box.HtmlTag.Name == "html" && box.HtmlContainer.CssData != null)
                    {
                        sb.AppendLine("<head>");
                        WriteStylesheet(sb, box.HtmlContainer.CssData);
                        sb.AppendLine("</head>");
                    }
                }

                if (box.Words.Count > 0)
                {
                    foreach (var word in box.Words)
                    {
                        if (selectedBoxes == null || word.Selected)
                        {
                            var wordText = GetSelectedWord(word, selectedBoxes != null);
                            sb.Append(HtmlUtils.EncodeHtml(wordText));
                        }
                    }
                }

                foreach (var childBox in box.Boxes)
                {
                    WriteHtml(cssParser, sb, childBox, styleGen, selectedBoxes, selectionRoot);
                }

                if (box.HtmlTag != null && !box.HtmlTag.IsSingle)
                {
                    if (box == selectionRoot)
                        sb.Append("<!--EndFragment-->");
                    sb.AppendFormat("</{0}>", box.HtmlTag.Name);
                }
            }
        }