private static IEnumerable<Assert> DeserializeAsserts(XElement xRule, XmlNamespaceManager nsManager)
        {
            List<Assert> listAssert = new List<Assert>();
            foreach (XElement xAssert in xRule.XPathSelectElements("sch:assert|sch:report", nsManager))
            {
                Assert assert = new Assert();

                // @id
                XAttribute xId = xAssert.Attribute(XName.Get("id"));
                if (xId != null)
                {
                    assert.Id = xId.Value;
                }

                // @test
                assert.Test = xAssert.Attribute(XName.Get("test")).Value;

                // assert vs. report
                if (xAssert.Name.LocalName == "report")
                {
                    assert.IsReport = true;
                    assert.Test = String.Format("not({0})", assert.Test);
                }
                else
                {
                    assert.IsReport = false;
                }

                // resolve content
                if (xAssert.HasElements)
                {
                    ResolveAssertContent(xAssert, assert, nsManager);
                }
                else
                {
                    assert.Diagnostics = new string[0];
                    assert.Message = xAssert.Value;
                }

                listAssert.Add(assert);
            }

            return listAssert;
        }
        private void ValidateAssert(Pattern pattern, Rule rule, Assert assert, XPathNavigator context)
        {
            // evaluate test
            object objResult = context.Evaluate(assert.CompiledTest);

            // resolve object result
            bool isViolated = false;
            switch (assert.CompiledTest.ReturnType)
            {
                case XPathResultType.Boolean:
                    {
                        isViolated = !Convert.ToBoolean(objResult);
                        break;
                    }
                case XPathResultType.Number:
                    {
                        double value = Convert.ToDouble(objResult);
                        isViolated = double.IsNaN(value);
                        break;
                    }
                case XPathResultType.NodeSet:
                    {
                        XPathNodeIterator iterator = (XPathNodeIterator)objResult;
                        isViolated = (iterator.Count == 0);
                        break;
                    }
                default:
                    throw new InvalidOperationException(String.Format("'{0}'.", assert.Test));
            }

            // results
            if (isViolated)
            {
                if (!this.fullValidation)
                {
                    this.isCanceled = true;
                }

                this.results.IsValid = false;

                AssertionInfo info = new AssertionInfo();
                info.IsReport = assert.IsReport;
                info.PatternId = pattern.Id;
                info.RuleId = rule.Id;
                info.RuleContext = rule.Context;
                info.AssertionId = assert.Id;
                info.AssertionTest = assert.Test;
                info.UserMessage = CreateUserMessage(assert, context);
                info.Location = CreateLocation(context);

                IXmlLineInfo lineInfo = (IXmlLineInfo)context;
                info.LineNumber = lineInfo.LineNumber;
                info.LinePosition = lineInfo.LinePosition;

                this.results.ViolatedAssertionsList.Add(info);
            }
        }
        private string CreateUserMessage(Assert assert, XPathNavigator context)
        {
            if (assert.Diagnostics.Length == 0)
            {
                return assert.Message.Trim();
            }
            else
            {
                List<string> diagValues = new List<string>();

                foreach (XPathExpression xpeDiag in assert.CompiledDiagnostics)
                {
                    object objDiagResult = context.Evaluate(xpeDiag);

                    // resolve diag result object
                    switch (xpeDiag.ReturnType)
                    {
                        case XPathResultType.Number:
                        case XPathResultType.String:
                            {
                                diagValues.Add(objDiagResult.ToString());
                                break;
                            }
                        case XPathResultType.Boolean:
                            {
                                diagValues.Add(objDiagResult.ToString().ToLower());
                                break;
                            }
                        case XPathResultType.NodeSet:
                            {
                                XPathNodeIterator iterator = (XPathNodeIterator)objDiagResult;
                                if (iterator.Count > 0)
                                {
                                    foreach (var x in iterator)
                                    {
                                        diagValues.Add(x.ToString());
                                        break;
                                    }
                                }
                                else
                                {
                                    diagValues.Add(string.Empty);
                                }
                                break;
                            }
                        default:
                            diagValues.Add(string.Empty);
                            break;
                    }
                }

                return String.Format(assert.Message, diagValues.ToArray()).Trim();
            }
        }
        private static void ResolveAssertContent(XElement xAssert, Assert assert, XmlNamespaceManager nsManager)
        {
            List<string> diagnostics = new List<string>();
            List<bool> diagnosticsIsValueOf = new List<bool>();

            XName nameElement = XName.Get("name", Constants.ISONamespace);
            XName valueofElement = XName.Get("value-of", Constants.ISONamespace);

            StringBuilder sbMessage = new StringBuilder();
            foreach (XNode node in xAssert.DescendantNodes())
            {
                if (!(node is XElement))
                {
                    sbMessage.Append(node.ToString());
                }
                else
                {
                    XElement xEle = (XElement)node;

                    // resolve name, value-of
                    string xpathDiagnostic = null;
                    if (xEle.Name == nameElement)
                    {
                        diagnosticsIsValueOf.Add(false);
                        xpathDiagnostic = "name()";
                        XAttribute xPath = xEle.Attribute(XName.Get("path"));
                        if (xPath != null)
                        {
                            xpathDiagnostic = String.Format(String.Format("name({0})", xPath.Value));
                        }
                    }
                    else if (xEle.Name == valueofElement)
                    {
                        diagnosticsIsValueOf.Add(true);
                        xpathDiagnostic = xEle.Attribute(XName.Get("select")).Value;
                    }

                    if (xpathDiagnostic != null)
                    {
                        // get collection index
                        int index = diagnostics.IndexOf(xpathDiagnostic);
                        if (index < 0)
                        {
                            diagnostics.Add(xpathDiagnostic);
                            index = diagnostics.Count - 1;
                        }

                        sbMessage.Append("{");
                        sbMessage.Append(index);
                        sbMessage.Append("}");
                        index++;
                    }
                }
            }

            assert.Message = sbMessage.ToString();
            assert.Diagnostics = diagnostics.ToArray();
            assert.DiagnosticsIsValueOf = diagnosticsIsValueOf.ToArray();
        }