Finds view-level formatting rules. These are a little tricky because they are implemented by sprinkling xsl logic into our views. As such, a particular formatting rule could show up in multiple places, or merge-ish with other rules.
상속: InfoPathFeature
        public static IEnumerable<InfoPathFeature> ParseFeature(XDocument document)
        {
            IEnumerable<XElement> allElements = document.Descendants(xslNamespace + xslAttribute);
            foreach (XElement element in allElements)
            {
                XAttribute name = element.Attribute(nameAttribute);
                // these are the html attributes that we try to set.
                // specifically for conditional hide we have to look under a style for an xsl:when with .Text() contains "DISPLAY: none"
                if (name.Value.Equals(contentEditable))
                {
                    FormattingRule rule = new FormattingRule();
                    rule.FormatType = "Readonly";
                    yield return rule;
                }
                else if (name.Value.Equals(style))
                {
                    Utilities.BucketCounter counter = new Utilities.BucketCounter();
                    FormattingRule rule = new FormattingRule();
                    rule.FormatType = "Style";
                    // now let's count all the things we're affecting.
                    // Overloading BucketCounter to filter the noise of multiple touches to same style
                    foreach (XElement xslWhen in element.Descendants(xslNamespace + when))
                    {
                        string[] styles = xslWhen.Value.Split(new char[] { ';' });
                        foreach (string s in styles)
                        {
                            if (s.Trim().StartsWith("caption:")) continue;
                            string affectedStyle = s.Split(':')[0].Trim().ToUpper();
                            counter.IncrementKey(affectedStyle);
                        }
                    }
                    StringBuilder sb = new StringBuilder();
                    foreach (KeyValuePair<string, int> kvp in counter.Buckets)
                    {
                        sb.Append(kvp.Key).Append(" ");
                    }
                    rule.SubDetails = sb.ToString().Trim();
                    yield return rule;
                }
            }

            // nothing left
            yield break;
        }