/// <summary>
        /// Creates a new ContextDocumentReadWrite using the XmlReader instance provided.
        /// </summary>
        /// <param name="reader">The XmlReader instance positioned at the begining of the document.</param>
        /// <param name="schemaVersion">The schema used to validate this context document.</param>
        public ContextDocumentReadWrite(XmlReader reader, XacmlVersion schemaVersion)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            // Search for the first element.
            while (reader.Read() && reader.NodeType != XmlNodeType.Element)
            {
            }

            // Keep the contents of the context document.
            // HACK: Due to XPath validation the document must be readed twice, the first time to load the instance
            // and the second one to keep a document to execute XPath sentences.
            _xmlString = reader.ReadOuterXml();

            // Read the contents in a new reader.
            var sreader = new StringReader(_xmlString);

            // Prepare the validation.
            var validationHandler = new ValidationEventHandler(vreader_ValidationEventHandler);
            var settings          = new XmlReaderSettings {
                ValidationType = ValidationType.Schema
            };

            settings.ValidationEventHandler += validationHandler;
            XmlReader vreader = null;

            try
            {
                switch (schemaVersion)
                {
                case XacmlVersion.Version10:
                case XacmlVersion.Version11:
                {
                    if (_compiledSchemas11 == null)
                    {
                        var policySchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(PolicyDocumentReadWrite.Xacml10PolicySchemaResourceName);
                        Debug.Assert(policySchemaStream != null);
                        var contextSchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Xacml10ContextSchemaResourceName);
                        Debug.Assert(contextSchemaStream != null);
                        _compiledSchemas11 = new XmlSchemaSet();
                        _compiledSchemas11.Add(XmlSchema.Read(policySchemaStream, validationHandler));
                        _compiledSchemas11.Add(XmlSchema.Read(contextSchemaStream, validationHandler));
                        _compiledSchemas11.Compile();
                    }
                    settings.Schemas.Add(_compiledSchemas11);
                    break;
                }

                case XacmlVersion.Version20:
                {
                    if (_compiledSchemas20 == null)
                    {
                        Stream policySchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(PolicyDocumentReadWrite.Xacml20PolicySchemaResourceName);
                        Debug.Assert(policySchemaStream != null);
                        Stream contextSchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Xacml20ContextSchemaResourceName);
                        Debug.Assert(contextSchemaStream != null);
                        _compiledSchemas20 = new XmlSchemaSet();
                        _compiledSchemas20.Add(XmlSchema.Read(policySchemaStream, validationHandler));
                        _compiledSchemas20.Add(XmlSchema.Read(contextSchemaStream, validationHandler));
                        _compiledSchemas20.Compile();
                    }
                    settings.Schemas.Add(_compiledSchemas20);
                    break;
                }

                default:
                    throw new ArgumentException("ÒâÍâµÄ°æ±¾ºÅ" + schemaVersion);
                }
                vreader = XmlReader.Create(sreader, settings);
                while (vreader.Read())
                {
                    //Read all the namespaces and keep them in the _namespaces hashtable.
                    if (vreader.HasAttributes)
                    {
                        while (vreader.MoveToNextAttribute())
                        {
                            if (vreader.LocalName == Consts.Schema1.Namespaces.Xmlns)
                            {
                                _namespaces.Add(vreader.Prefix, vreader.Value);
                            }
                            else if (vreader.Prefix == Consts.Schema1.Namespaces.Xmlns)
                            {
                                _namespaces.Add(vreader.LocalName, vreader.Value);
                            }
                        }
                        vreader.MoveToElement();
                    }
                    switch (vreader.LocalName)
                    {
                    case Consts.ContextSchema.RequestElement.Request:
                        _request = new RequestElementReadWrite(vreader, schemaVersion);
                        break;

                    case Consts.ContextSchema.ResponseElement.Response:
                        Response = new ResponseElement(vreader, schemaVersion);
                        break;
                    }
                }
            }
            finally
            {
                if (vreader != null)
                {
                    vreader.Close();
                }
            }
        }
        /// <summary>
        /// Creates a new ContextDocumentReadWrite using the XmlReader instance provided.
        /// </summary>
        /// <param name="reader">The XmlReader instance positioned at the begining of the document.</param>
        /// <param name="schemaVersion">The schema used to validate this context document.</param>
        public ContextDocumentReadWrite(XmlReader reader, XacmlVersion schemaVersion)
        {
            if (reader == null) throw new ArgumentNullException("reader");
            // Search for the first element.
            while (reader.Read() && reader.NodeType != XmlNodeType.Element)
            { }

            // Keep the contents of the context document.
            // HACK: Due to XPath validation the document must be readed twice, the first time to load the instance
            // and the second one to keep a document to execute XPath sentences.
            _xmlString = reader.ReadOuterXml();

            // Read the contents in a new reader.
            var sreader = new StringReader(_xmlString);

            // Prepare the validation.
            var validationHandler = new ValidationEventHandler(vreader_ValidationEventHandler);
            var settings = new XmlReaderSettings { ValidationType = ValidationType.Schema };
            settings.ValidationEventHandler += validationHandler;
            XmlReader vreader = null;
            try
            {
                switch (schemaVersion)
                {
                    case XacmlVersion.Version10:
                    case XacmlVersion.Version11:
                        {
                            if (_compiledSchemas11 == null)
                            {
                                var policySchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(PolicyDocumentReadWrite.Xacml10PolicySchemaResourceName);
                                Debug.Assert(policySchemaStream != null);
                                var contextSchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Xacml10ContextSchemaResourceName);
                                Debug.Assert(contextSchemaStream != null);
                                _compiledSchemas11 = new XmlSchemaSet();
                                _compiledSchemas11.Add(XmlSchema.Read(policySchemaStream, validationHandler));
                                _compiledSchemas11.Add(XmlSchema.Read(contextSchemaStream, validationHandler));
                                _compiledSchemas11.Compile();
                            }
                            settings.Schemas.Add(_compiledSchemas11);
                            break;
                        }
                    case XacmlVersion.Version20:
                        {
                            if (_compiledSchemas20 == null)
                            {
                                Stream policySchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(PolicyDocumentReadWrite.Xacml20PolicySchemaResourceName);
                                Debug.Assert(policySchemaStream != null);
                                Stream contextSchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Xacml20ContextSchemaResourceName);
                                Debug.Assert(contextSchemaStream != null);
                                _compiledSchemas20 = new XmlSchemaSet();
                                _compiledSchemas20.Add(XmlSchema.Read(policySchemaStream, validationHandler));
                                _compiledSchemas20.Add(XmlSchema.Read(contextSchemaStream, validationHandler));
                                _compiledSchemas20.Compile();
                            }
                            settings.Schemas.Add(_compiledSchemas20);
                            break;
                        }
                    default:
                        throw new ArgumentException("ÒâÍâµÄ°æ±¾ºÅ" + schemaVersion);
                }
                vreader = XmlReader.Create(sreader, settings);
                while (vreader.Read())
                {
                    //Read all the namespaces and keep them in the _namespaces hashtable.
                    if (vreader.HasAttributes)
                    {
                        while (vreader.MoveToNextAttribute())
                        {
                            if (vreader.LocalName == Consts.Schema1.Namespaces.Xmlns)
                            {
                                _namespaces.Add(vreader.Prefix, vreader.Value);
                            }
                            else if (vreader.Prefix == Consts.Schema1.Namespaces.Xmlns)
                            {
                                _namespaces.Add(vreader.LocalName, vreader.Value);
                            }
                        }
                        vreader.MoveToElement();
                    }
                    switch (vreader.LocalName)
                    {
                        case Consts.ContextSchema.RequestElement.Request:
                            _request = new RequestElementReadWrite(vreader, schemaVersion);
                            break;
                        case Consts.ContextSchema.ResponseElement.Response:
                            Response = new ResponseElement(vreader, schemaVersion);
                            break;
                    }
                }
            }
            finally
            {
                if (vreader != null)
                {
                    vreader.Close();
                }
            }
        }