/// <summary>
        /// Instantiates a reader object for the given XML PrintCapabilities
        /// </summary>
        /// <remarks>Constructor verifies the root element is valid</remarks>
        /// <exception cref="FormatException">thrown if XML PrintCapabilities is not well-formed</exception>
        public XmlPrintCapReader(Stream xmlStream)
        {
            // Internally the XML PrintCapabilities reader uses XmlTextReader
            _xmlReader = new XmlTextReader(xmlStream);

            // We need namespace support from the reader.
            _xmlReader.Namespaces = true;

            // Don't resolve external resources.
            _xmlReader.XmlResolver = null;

            // Verify root element is <PrintCapabilities> in our standard namespace
            if ((_xmlReader.MoveToContent() != XmlNodeType.Element) ||
                (_xmlReader.LocalName != PrintSchemaTags.Framework.PrintCapRoot) ||
                (_xmlReader.NamespaceURI != PrintSchemaNamespaces.Framework))
            {
                throw NewPrintCapFormatException(String.Format(CultureInfo.CurrentCulture,
                                                               PTUtility.GetTextFromResource("FormatException.InvalidRootElement"),
                                                               _xmlReader.NamespaceURI,
                                                               _xmlReader.LocalName));
            }

            // Verify the XML PrintCapabilities version is supported

            // For XML attribute without a prefix (e.g. <... name="prn:PageMediaSize">),
            // even though the XML document has default namespace defined as our standard
            // Print Schema framework namespace, the XML atribute still has NULL namespaceURI.
            // It will only have the correct namespaceURI when a prefix is used. This doesn't
            // apply to XML element, whose namespaceURI works fine with default namespace.

            // GetAttribute doesn't move the reader cursor away from the current element
            string version = _xmlReader.GetAttribute(PrintSchemaTags.Framework.RootVersionAttr,
                                                     PrintSchemaNamespaces.FrameworkAttrForXmlReader);

            if (version == null)
            {
                throw NewPrintCapFormatException(String.Format(CultureInfo.CurrentCulture,
                                                               PTUtility.GetTextFromResource("FormatException.RootMissingAttribute"),
                                                               PrintSchemaTags.Framework.RootVersionAttr));
            }

            // Convert string to number to verify
            decimal versionNum;

            try
            {
                versionNum = XmlConvertHelper.ConvertStringToDecimal(version);
            }
            catch (FormatException e)
            {
                throw NewPrintCapFormatException(String.Format(CultureInfo.CurrentCulture,
                                                               PTUtility.GetTextFromResource("FormatException.RootInvalidAttribute"),
                                                               PrintSchemaTags.Framework.RootVersionAttr,
                                                               version),
                                                 e);
            }

            if (versionNum != PrintSchemaTags.Framework.SchemaVersion)
            {
                throw NewPrintCapFormatException(String.Format(CultureInfo.CurrentCulture,
                                                               PTUtility.GetTextFromResource("FormatException.VersionNotSupported"),
                                                               versionNum));
            }

            // Reset internal states to be ready for client's reading of the PrintCapabilities XML
            ResetCurrentElementState();
        }
예제 #2
0
        /// <summary>
        /// Verifies if the PrintTicket is well-formed
        /// </summary>
        /// <exception cref="FormatException">
        /// The PrintTicket is not well-formed.
        /// </exception>
        public static void CheckIsWellFormedPrintTicket(InternalPrintTicket pt)
        {
            XmlElement root = pt.XmlDoc.DocumentElement;

            // Root element should be in our standard namespace and should be <PrintTicket>.
            if ((root.NamespaceURI != PrintSchemaNamespaces.Framework) ||
                (root.LocalName != PrintSchemaTags.Framework.PrintTicketRoot))
            {
                throw NewPTFormatException(String.Format(CultureInfo.CurrentCulture,
                                                         PTUtility.GetTextFromResource("FormatException.InvalidRootElement"),
                                                         root.NamespaceURI,
                                                         root.LocalName));
            }

            string version = root.GetAttribute(PrintSchemaTags.Framework.RootVersionAttr,
                                               PrintSchemaNamespaces.FrameworkAttrForXmlDOM);

            // Root element should have the "version" attribute
            // (XmlElement.GetAttribute returns empty string when the attribute is not found, but
            // (XmlTextReader.GetAttribute returns null when the attribute is not found)
            if ((version == null) || (version.Length == 0))
            {
                throw NewPTFormatException(String.Format(CultureInfo.CurrentCulture,
                                                         PTUtility.GetTextFromResource("FormatException.RootMissingAttribute"),
                                                         PrintSchemaTags.Framework.RootVersionAttr));
            }

            decimal versionNum;

            try
            {
                versionNum = XmlConvertHelper.ConvertStringToDecimal(version);
            }
            catch (FormatException e)
            {
                throw NewPTFormatException(String.Format(CultureInfo.CurrentCulture,
                                                         PTUtility.GetTextFromResource("FormatException.RootInvalidAttribute"),
                                                         PrintSchemaTags.Framework.RootVersionAttr,
                                                         version),
                                           e);
            }

            // and the "version" attribute value should be what we support
            if (versionNum != PrintSchemaTags.Framework.SchemaVersion)
            {
                throw NewPTFormatException(String.Format(CultureInfo.CurrentCulture,
                                                         PTUtility.GetTextFromResource("FormatException.VersionNotSupported"),
                                                         versionNum));
            }

            // Now go through each root child element and verify they are valid children
            XmlNode rootChild = root.FirstChild;

            // It's recommended that traversing the node in forward-only movement by using NextSibling
            // is best for XmlDocument performance. This is because the list is not double-linked.
            while (rootChild != null)
            {
                // If the root child doesn't live in our standard namespace, we should ignore it
                // rather than rejecting it since it's acceptable to have private elements under
                // the root.
                if (rootChild.NamespaceURI == PrintSchemaNamespaces.Framework)
                {
                    // For <PrintTicket> root, our Framework schema only allow these children elements:
                    // <Feature> <AttributeSet> <Property> <ParameterInit>
                    if ((rootChild.NodeType != XmlNodeType.Element) ||
                        ((rootChild.LocalName != PrintSchemaTags.Framework.Feature) &&
                         (rootChild.LocalName != PrintSchemaTags.Framework.ParameterInit) &&
                         (rootChild.LocalName != PrintSchemaTags.Framework.Property)))
                    {
                        throw NewPTFormatException(String.Format(CultureInfo.CurrentCulture,
                                                                 PTUtility.GetTextFromResource("FormatException.RootInvalidChildElement"),
                                                                 rootChild.Name));
                    }

                    string childName = ((XmlElement)rootChild).GetAttribute(PrintSchemaTags.Framework.NameAttr,
                                                                            PrintSchemaNamespaces.FrameworkAttrForXmlDOM);

                    // All the recognized root child element should have an XML attribut "name"
                    if ((childName == null) || (childName.Length == 0))
                    {
                        throw NewPTFormatException(String.Format(CultureInfo.CurrentCulture,
                                                                 PTUtility.GetTextFromResource("FormatException.RootChildMissingAttribute"),
                                                                 rootChild.Name,
                                                                 PrintSchemaTags.Framework.NameAttr));
                    }
                }

                rootChild = rootChild.NextSibling;
            }

            // We will end the verification at the root child level here. Instead of traversing the whole tree
            // to find violations in this construtor, we will delay detecting violations under root child level
            // until information of an individual feature/property subtree is requested.
        }