/// <summary>
        /// Gets current Property/ScoredProperty's QName LocalName value from its "Value" child-element.
        /// The returned property QName value is guaranteed to be in the standard keyword set namespace.
        /// </summary>
        /// <exception cref="FormatException">either can't find the value or value is private</exception>
        /// <exception cref="XmlException">XML is not well-formed.</exception>
        public string GetCurrentPropertyQNameValueWithException()
        {
            string QName = GetCurrentPropertyFullValueWithException();

            if (XmlReaderQName.GetURI(_xmlReader, QName) == PrintSchemaNamespaces.StandardKeywordSet)
            {
                return(XmlReaderQName.GetLocalName(QName));
            }
            else
            {
                // Needs to handle private XML text value
                throw NewPrintCapFormatException(String.Format(CultureInfo.CurrentCulture,
                                                               PTUtility.GetTextFromResource("FormatException.PrivateXMLTextValue"),
                                                               QName,
                                                               _xmlReader.LineNumber,
                                                               _xmlReader.LinePosition));
            }
        }
        /// <summary>
        /// Moves the reader cursor to the next Print Schema Framework element at the given depth.
        /// (The element could be Feature, ParameterDefinition, Option, ScoredProperty or Property)
        /// </summary>
        /// <param name="depth">client-requested traversing depth</param>
        /// <param name="typeFilterFlags">flags to indicate client interested node types</param>
        /// <returns>True if next Framework element is ready to read.
        /// False if no more Framework element at the given depth.</returns>
        /// <exception cref="XmlException">XML is not well-formed.</exception>
        public bool MoveToNextSchemaElement(int depth, PrintSchemaNodeTypes typeFilterFlags)
        {
            bool foundElement = false;

            while (!foundElement && _xmlReader.Read())
            {
                // Read() throws XmlException if error occurred while parsing the XML.

                // If we hit an end-element tag at higher depth, we know there are no more
                // Framework elements at the client-requested depth.
                if ((_xmlReader.NodeType == XmlNodeType.EndElement) &&
                    (_xmlReader.Depth < depth))
                {
                    break;
                }

                // Stop at the next XML start element at the client-requested depth
                // and in the standard Framework element namespace.
                if ((_xmlReader.NodeType != XmlNodeType.Element) ||
                    (_xmlReader.Depth != depth) ||
                    (_xmlReader.NamespaceURI != PrintSchemaNamespaces.Framework))
                {
                    continue;
                }

                // Find a candidate, so reset internal states to be ready for its parsing.
                ResetCurrentElementState();

                foundElement = true;

                _currentElementDepth   = depth;
                _currentElementIsEmpty = _xmlReader.IsEmptyElement;

                // Map element name to Schema node type
                int enumValue = PrintSchemaMapper.SchemaNameToEnumValueWithMap(
                    PrintSchemaTags.Framework.NodeTypeMapTable,
                    _xmlReader.LocalName);

                if (enumValue > 0)
                {
                    _currentElementNodeType = (PrintSchemaNodeTypes)enumValue;
                }
                else
                {
                    #if _DEBUG
                    Trace.WriteLine("-Warning- skip unknown element '" + _xmlReader.LocalName +
                                    "' at line " + _xmlReader.LineNumber + ", position " +
                                    _xmlReader.LinePosition);
                    #endif

                    foundElement = false;
                }

                if (foundElement)
                {
                    // Check whether or not the found element type is what client is interested in.
                    // If not, we will skip this element.
                    if ((CurrentElementNodeType & typeFilterFlags) == 0)
                    {
                        #if _DEBUG
                        Trace.WriteLine("-Warning- skip not-wanted element '" + _xmlReader.LocalName +
                                        "' at line " + _xmlReader.LineNumber + ", position " +
                                        _xmlReader.LinePosition);
                        #endif

                        foundElement = false;
                    }
                }

                if (foundElement)
                {
                    // The element is what the client wants.
                    if (CurrentElementNodeType != PrintSchemaNodeTypes.Value)
                    {
                        // Element other than <Value> should have the "name" XML attribute.
                        // Reader will verify the "name" XML attribute has a QName value that
                        // is in our standard Keyword namespace.
                        string QName = _xmlReader.GetAttribute(PrintSchemaTags.Framework.NameAttr,
                                                               PrintSchemaNamespaces.FrameworkAttrForXmlReader);

                        // Only <Option> element is allowed not to have the "name" XML attribute
                        if (QName == null)
                        {
                            if (CurrentElementNodeType != PrintSchemaNodeTypes.Option)
                            {
                                #if _DEBUG
                                Trace.WriteLine("-Warning- skip element " + CurrentElementNodeType +
                                                " at line " + _xmlReader.LineNumber + ", position " +
                                                _xmlReader.LinePosition + " due to missing 'name' XML attribute");
                                #endif

                                foundElement = false;
                            }
                        }
                        else
                        {
                            string URI       = XmlReaderQName.GetURI(_xmlReader, QName);
                            string localName = XmlReaderQName.GetLocalName(QName);

                            if (URI == PrintSchemaNamespaces.Framework)
                            {
                                _currentElementPSFNameAttrValue = localName;
                            }
                            else if (URI == PrintSchemaNamespaces.StandardKeywordSet)
                            {
                                _currentElementNameAttrValue = localName;
                            }
                            else
                            {
                                // If QName value is not in standard PSF or PSK namespace,
                                // then skip this Schema element.
                                #if _DEBUG
                                Trace.WriteLine("-Warning- skip element " + CurrentElementNodeType +
                                                " at line " + _xmlReader.LineNumber + ", position " +
                                                _xmlReader.LinePosition +
                                                " due to non-PSF/PSK 'name' XML attribute value: " + QName);
                                #endif

                                foundElement = false;
                            }
                        }
                    }
                    else
                    {
                        // For <Value> element, we need to get its element text value.
                        // If this function tells client the <Value> element is found, it guarantees
                        // that the <Value> element text value is non-empty.

                        // Needs to handle xsi:type verification
                        // ReadElementString() returns empty string if the element is empty
                        // (<item></item> or <item/>), and it could throws XmlException.
                        _currentElementTextValue = _xmlReader.ReadElementString();

                        // Our schema requires that <Value> element should always have non-empty value.
                        if ((_currentElementTextValue == null) || (_currentElementTextValue.Length == 0))
                        {
                            #if _DEBUG
                            Trace.WriteLine("-Warning- skip element " + CurrentElementNodeType +
                                            " at line " + _xmlReader.LineNumber + ", position " +
                                            _xmlReader.LinePosition + " since it has empty element text");
                            #endif

                            _currentElementTextValue = null;
                            foundElement             = false;
                        }
                    }
                }
            }

            return(foundElement);
        }