All Downloads are FREE. Search and download functionalities are using the official Maven repository.

aSaxon-B-9-0-0-8sources.api.Saxon.Api.Model.cs Maven / Gradle / Ivy

Go to download

The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.

The newest version!
using System;
using System.IO;
using System.Xml;
using System.Collections;
using JConfiguration = net.sf.saxon.Configuration;
using JAtomicValue = net.sf.saxon.value.AtomicValue;
using JConversionResult = net.sf.saxon.type.ConversionResult;
using JValidationFailure = net.sf.saxon.type.ValidationFailure;
using JStandardNames = net.sf.saxon.om.StandardNames;
using DotNetReceiver = net.sf.saxon.dotnet.DotNetReceiver;
using DotNetObjectValue = net.sf.saxon.dotnet.DotNetObjectValue;
using JBigDecimal = java.math.BigDecimal;
using JArrayList = java.util.ArrayList;
using net.sf.saxon.om;
using net.sf.saxon.value;
using net.sf.saxon.pattern;
using JAtomicType = net.sf.saxon.type.AtomicType;
using JSchemaType = net.sf.saxon.type.SchemaType;
using JType = net.sf.saxon.type.Type;


namespace Saxon.Api {

    /// 
    /// An value in the XDM data model. A value is a sequence of zero or more
    /// items, each item being either an atomic value or a node.
    /// 
    /// 
    /// An XdmValue is immutable.
    /// A sequence consisting of a single item may be represented
    /// as an instance of XdmItem, which is a subtype of XdmValue.
    /// 

    [Serializable]
    public class XdmValue : IEnumerable {

        internal ValueRepresentation value;

        internal XdmValue() { }

        /// 
        /// Create a value from a collection of items
        /// 
        /// An enumerable collection providing the items to make up the sequence. Every
        /// member of this collection must be an instance of XdmItem
        /// 

        public XdmValue(IEnumerable items) {
            JArrayList list = new JArrayList();
            foreach (XdmItem c in items) {
                list.add((Item)c.Unwrap());
            }
            value = new SequenceExtent(list);
        }

        /// 
        /// Create an XdmValue from an underlying Saxon ValueRepresentation object.
        /// This method is provided for the benefit of applications that need to mix
        /// use of the Saxon .NET API with direct use of the underlying objects
        /// and methods offered by the Java implementation.
        /// 
        /// An object representing an XDM value in the
        /// underlying Saxon implementation.
        /// An XdmValue that wraps the underlying Saxon value
        /// representation.

        public static XdmValue Wrap(ValueRepresentation value) {
            XdmValue result;
            if (value == null || value is EmptySequence) {
                return XdmEmptySequence.INSTANCE;
            } else if (value is JAtomicValue) {
                result = new XdmAtomicValue();
            } else if (value is NodeInfo) {
                result = new XdmNode();
            } else {
                result = new XdmValue();
            }
            result.value = value;
            return result;
        }

        /// 
        /// Extract the underlying Saxon ValueRepresentation object from an XdmValue.
        /// This method is provided for the benefit of applications that need to mix
        /// use of the Saxon .NET API with direct use of the underlying objects
        /// and methods offered by the Java implementation.
        /// 
        /// An object representing the XDM value in the
        /// underlying Saxon implementation.


        public ValueRepresentation Unwrap() {
            return value;
        }

        /// 
        /// Get the sequence of items in the form of an IList
        /// 
        /// 
        /// The list of items making up this value. Each item in the list
        /// will be an object of type XdmItem
        ///         

        public IList GetList() {
            if (value == null) {
                return new ArrayList();
            } else if (value is Item) {
                ArrayList list = new ArrayList(1);
                list.Add((NodeInfo)value);
                return list;
            } else {
                ArrayList list = new ArrayList();
                SequenceIterator iter = ((Value)value).iterate();
                while (true) {
                    Item jitem = iter.next();
                    if (jitem == null) {
                        break;
                    }
                    list.Add((XdmItem)XdmValue.Wrap(jitem));
                }
                return list;
            }
        }

        /// 
        /// Get the sequence of items in the form of an IEnumerator
        /// 
        /// 
        /// An enumeration over the list of items making up this value. Each item in the list
        /// will be an object of type XdmItem
        ///     

        public IEnumerator GetEnumerator() {
            if (value == null) {
                return EmptyEnumerator.INSTANCE;
            } else if (value is Item) {
                return new SequenceEnumerator(SingletonIterator.makeIterator((Item)value));
            } else {
                return new SequenceEnumerator(((Value)value).iterate());
            }
        }

        /// 
        /// Get the number of items in the sequence
        /// 
        /// 
        /// The number of items in the sequence
        ///  

        public int Count {
            get {
                if (value == null) {
                    return 0;
                } else if (value is Item) {
                    return 1;
                } else {
                    return ((Value)value).getLength();
                }
            }
        }


    }

    /// 
    /// The class XdmItem represents an item in a sequence, as defined
    /// by the XDM data model. An item is either an atomic value or a node.
    /// 
    /// 
    /// An item is a member of a sequence, but it can also be considered as
    /// a sequence (of length one) in its own right. XdmItem is a subtype
    /// of XdmValue because every Item in the XDM data model is also a
    /// value.
    /// It cannot be assumed that every sequence of length one will be 
    /// represented by an XdmItem. It is quite possible for an XdmValue
    /// that is not an XdmItem to hold a singleton sequence.
    ///  

    [Serializable]
    public abstract class XdmItem : XdmValue {

        /// 
        /// Determine whether the item is an atomic value
        /// 
        /// 
        /// true if the item is an atomic value, false if it is a Node
        /// 

        public abstract bool IsAtomic();

    }

    /// 
    /// The class XdmAtomicValue represents an item in an XPath 2.0 sequence
    /// that is an atomic value. The value may belong to any of the 19 primitive types
    /// defined in XML Schema, or to a type derived from these primitive types, or to 
    /// the XPath 2.0 type xdt:untypedAtomic
    /// 

    [Serializable]
    public class XdmAtomicValue : XdmItem {

        //internal JAtomicValue atomicValue;

        internal XdmAtomicValue() { }

        /// 
        /// Determine whether the item is an atomic value
        /// 
        /// 
        /// true (the item is an atomic value)
        /// 

        public override bool IsAtomic() {
            return true;
        }

        //internal AtomicValue(JAtomicValue value) {
        //    this.value = value;
        //}

        /// 
        /// Construct an atomic value of type xs:string
        /// 
        /// The string value

        public XdmAtomicValue(String str) {
            this.value = new StringValue(str);
        }

        /// 
        /// Construct an atomic value of type xs:integer
        /// 
        /// The integer value

        public XdmAtomicValue(long i) {
            this.value = new Int64Value(i);
        }

        /// 
        /// Construct an atomic value of type xs:decimal
        /// 
        /// The decimal value

        public XdmAtomicValue(decimal d) {
            this.value = new DecimalValue(new JBigDecimal(d.ToString()));
        }

        /// 
        /// Construct an atomic value of type xs:float
        /// 
        /// The float value        

        public XdmAtomicValue(float f) {
            this.value = new FloatValue(f);
        }

        /// 
        /// Construct an atomic value of type xs:double
        /// 
        /// The double value

        public XdmAtomicValue(double d) {
            this.value = new DoubleValue(d);
        }

        /// 
        /// Construct an atomic value of type xs:boolean
        /// 
        /// The boolean value

        public XdmAtomicValue(bool b) {
            this.value = BooleanValue.get(b);
        }

        /// 
        /// Construct an atomic value of type xs:anyURI
        /// 
        /// The uri value

        public XdmAtomicValue(Uri u) {
            this.value = new AnyURIValue(u.ToString());
        }

        /// 
        /// Construct an atomic value of type xs:QName
        /// 
        /// The QName value                

        public XdmAtomicValue(QName q) {
            this.value = new QNameValue(
                q.Prefix, q.Uri, q.LocalName, null);
        }

        /// 
        /// Construct an atomic value of a given built-in or user-defined type
        /// 
        /// 
        ///   AtomicValue("abcd", QName.XDT_UNTYPED_ATOMIC)
        ///   creates an untyped atomic value containing the string "abcd"
        /// 
        /// The string representation of the value (any value that is acceptable
        /// in the lexical space, as defined by XML Schema Part 2). Whitespace normalization as defined by
        /// the target type will be applied to the value.
        /// The QName giving the name of the target type. This must be an atomic
        /// type, and it must not be a type that is namespace-sensitive (QName, NOTATION, or types derived
        /// from these). If the type is a user-defined type then its definition must be present
        /// in the schema cache maintained by the SchemaManager. 
        /// The Processor object. This is needed for looking up user-defined
        /// types, and also because some conversions are context-sensitive, for example they depend on the
        /// implicit timezone or the choice of XML 1.0 versus XML 1.1 for validating names.
        /// Thrown if the type is unknown or unsuitable, or if the supplied string is not
        /// a valid lexical representation of a value of the given type.

        public XdmAtomicValue(String lexicalForm, QName type, Processor processor) {
            JConfiguration jconfig = processor.config;
            int fp = jconfig.getNamePool().getFingerprint(type.Uri, type.LocalName);
            if (fp == -1) {
                throw new ArgumentException("Unknown name " + type);
            }
            JSchemaType st = jconfig.getSchemaType(fp);
            if (st == null) {
                throw new ArgumentException("Unknown type " + type);
            }
            if (!(st is JAtomicType)) {
                throw new ArgumentException("Specified type " + type + " is not atomic");
            }
            if (((JAtomicType)st).isNamespaceSensitive()) {
                throw new ArgumentException("Specified type " + type + " is namespace-sensitive");
            }
            JConversionResult result = new StringValue(lexicalForm).convert(
                    (JAtomicType)st,
                    true,
                    jconfig.getConversionContext());
            if (result is JValidationFailure) {
                throw new ArgumentException(((JValidationFailure)result).getMessage());
            }
            this.value = (JAtomicValue)result;
        }

        /// 
        /// Create an atomic value that wraps an external object. Such values can be used
        /// in conjunction with extension functions.
        /// 
        /// The object to be wrapped.
        /// The wrapped object

        public static XdmAtomicValue wrapExternalObject(object external) {
            return (XdmAtomicValue)XdmValue.Wrap(new DotNetObjectValue(external));
        }

        /// 
        /// Convert the atomic value to a string
        /// 
        /// The value converted to a string, according to the rules
        /// of the XPath 2.0 cast operator        

        public override String ToString() {
            return ((JAtomicValue)value).getStringValue();
        }

        /// 
        /// Get the name of the value's XDM type
        /// 
        /// The Processor object. 
        /// This is needed for access to the NamePool,
        /// which maps the internal form of type names to their external form.
        /// The type of the value, as a QName. This may be a built-in type or a user-defined
        /// atomic type.
        /// 


        public QName GetTypeName(Processor processor) {
            int fp = ((JAtomicType)((JAtomicValue)value).getItemType(null)).getFingerprint();
            NamePool pool = processor.config.getNamePool();
            return new QName(pool.getPrefix(fp),
                             pool.getURI(fp),
                             pool.getLocalName(fp));
        }

        /// 
        /// Get the name of the primitive type of the value
        /// 
        /// The primitive type of the value, as a QName. This will be the name of
        /// one of the primitive types defined in XML Schema Part 2, or the XPath-defined
        /// type xdt:untypedAtomic. For the purposes of this method, xs:integer is considered
        /// to be a primitive type.
        /// 


        public QName GetPrimitiveTypeName() {
            int fp = ((JAtomicValue)value).getItemType(null).getPrimitiveType();
            return new QName(JStandardNames.getPrefix(fp),
                             JStandardNames.getURI(fp),
                             JStandardNames.getLocalName(fp));
        }

        /// Get the value as a CLI object of the nearest equivalent type.
        /// 
        /// The return type is as follows:
        /// xs:string - String
        /// xs:integer - Long
        /// xs:decimal - Decimal
        /// xs:double - Double
        /// xs:float - Float
        /// xs:boolean - Bool
        /// xs:QName - QName
        /// xs:anyURI - Uri
        /// xdt:untypedAtomic - String
        /// Other types - currently String, but this may change in the future
        /// 
        /// The value converted to the most appropriate CLI type

        public Object Value {
            get {
                if (value is IntegerValue) {
                    return ((IntegerValue)value).longValue();
                } else if (value is DoubleValue) {
                    return ((DoubleValue)value).getDoubleValue();
                } else if (value is FloatValue) {
                    return ((FloatValue)value).getFloatValue();
                } else if (value is DecimalValue) {
                    return Decimal.Parse(((DecimalValue)value).getStringValue());
                } else if (value is BooleanValue) {
                    return ((BooleanValue)value).getBooleanValue();
                } else if (value is AnyURIValue) {
                    return new Uri(((AnyURIValue)value).getStringValue());
                } else if (value is QNameValue) {
                    return new QName((QNameValue)value);
                } else {
                    return ((JAtomicValue)value).getStringValue();
                }
            }
        }


    }

    /// 
    /// The class XdmNode represents a Node in the XDM Data Model. A Node
    /// is an XdmItem, and is therefore an XdmValue in its own right, and may also participate
    /// as one item within a sequence value.
    /// 
    /// 
    /// An XdmNode is implemented as a wrapper around an object
    /// of type net.sf.saxon.NodeInfo. Because this is a key interface
    /// within Saxon, it is exposed via this API, even though it is a Java
    /// interface that is not part of the API proper.
    /// The XdmNode interface exposes basic properties of the node, such
    /// as its name, its string value, and its typed value. Navigation to other nodes
    /// is supported through a single method, EnumerateAxis, which allows
    /// other nodes to be retrieved by following any of the XPath axes.
    /// 

    [Serializable]
    public class XdmNode : XdmItem {

        /// 
        /// Determine whether the item is an atomic value
        /// 
        /// 
        /// false (the item is not an atomic value)
        /// 

        public override bool IsAtomic() {
            return false;
        }

        /// 
        /// The name of the node, as a QName. Returns null in the case of unnamed nodes.
        /// 

        public QName NodeName {
            get {
                NodeInfo node = (NodeInfo)value;
                String local = node.getLocalPart();
                if (local == "") {
                    return null;
                }
                String prefix = node.getPrefix();
                String uri = node.getURI();
                return new QName(prefix, uri, local);
            }
        }

        /// 
        /// The kind of node, as an instance of System.Xml.XmlNodeType.
        /// 
        /// For a namespace node in the XDM model, the value XmlNodeType.None 
        /// is returned.
        /// 

        public XmlNodeType NodeKind {
            get {
                NodeInfo node = (NodeInfo)value;
                int kind = node.getNodeKind();
                switch (kind) {
                    case JType.DOCUMENT:
                        return XmlNodeType.Document;
                    case JType.ELEMENT:
                        return XmlNodeType.Element;
                    case JType.ATTRIBUTE:
                        return XmlNodeType.Attribute;
                    case JType.TEXT:
                        return XmlNodeType.Text;
                    case JType.COMMENT:
                        return XmlNodeType.Comment;
                    case JType.PROCESSING_INSTRUCTION:
                        return XmlNodeType.ProcessingInstruction;
                    case JType.NAMESPACE:
                        return XmlNodeType.None;
                    default:
                        throw new ArgumentException("Unknown node kind");
                }
            }
        }

        /// 
        /// The typed value of the node, as an instance of XdmValue.
        /// 
        /// 
        /// A DynamicError is thrown if the node has no typed value, as will be the case for
        /// an element with element-only content.
        /// 

        public XdmValue TypedValue {
            get { return XdmValue.Wrap(((NodeInfo)value).atomize()); }
        }

        /// 
        /// The string value of the node.
        /// 

        public String StringValue {
            get { return ((NodeInfo)value).getStringValue(); }
        }

        /// 
        /// Get the parent of this node.
        /// 
        /// 
        /// Returns either a document node, and element node, or null in the case where
        /// this node has no parent. 
        /// 

        public XdmNode Parent {
            get { return (XdmNode)XdmValue.Wrap(((NodeInfo)value).getParent()); }
        }

        /// 
        /// Get a the string value of a named attribute of this element. 
        /// 
        /// 
        /// Returns null if this node is not an element, or if this element has no
        /// attribute with the specified name.
        /// 
        
        public String GetAttributeValue(QName name) {
            int fp = ((NodeInfo)value).getConfiguration().getNamePool().allocate(
                name.Prefix, name.Uri, name.LocalName);
            return ((NodeInfo)value).getAttributeValue(fp);
        }

        /// 
        /// Get an enumerator that supplies all the nodes on one of the XPath
        /// axes, starting with this node.
        /// 
        /// 
        /// The axis to be navigated, for example XdmAxis.Child for the child axis.
        /// 
        /// 
        /// The nodes are returned in axis order: that is, document order for a forwards
        /// axis, reverse document order for a reverse axis.
        /// 

        public IEnumerator EnumerateAxis(XdmAxis axis) {
            return new SequenceEnumerator(((NodeInfo)value).iterateAxis(GetAxisNumber(axis)));
        }

        /// 
        /// Get an enumerator that selects all the nodes on one of the XPath
        /// axes, provided they have a given name. The nodes selected are those of the principal
        /// node kind (elements for most axes, attributes for the attribute axis, namespace nodes
        /// for the namespace axis) whose name matches the name given in the second argument.
        /// 
        /// 
        /// The axis to be navigated, for example XdmAxis.Child for the child axis.
        /// 
        /// 
        /// The name of the required nodes, for example new QName("", "item") to select
        /// nodes with local name "item", in no namespace.
        /// 
        /// 
        /// The nodes are returned in axis order: that is, document order for a forwards
        /// axis, reverse document order for a reverse axis.
        /// 

        public IEnumerator EnumerateAxis(XdmAxis axis, QName nodeName) {
            int kind;
            switch (axis) {
                case XdmAxis.Attribute:
                    kind = net.sf.saxon.type.Type.ATTRIBUTE;
                    break;
                case XdmAxis.Namespace:
                    kind = net.sf.saxon.type.Type.NAMESPACE;
                    break;
                default:
                    kind = net.sf.saxon.type.Type.ELEMENT;
                    break;
            }
            NamePool pool = ((NodeInfo)value).getConfiguration().getNamePool();
            int nameCode = pool.allocate("", nodeName.Uri, nodeName.LocalName);
            NameTest test = new NameTest(kind, nameCode, pool);
            return new SequenceEnumerator(((NodeInfo)value).iterateAxis(GetAxisNumber(axis), test));
        }

        private static byte GetAxisNumber(XdmAxis axis) {
            switch (axis) {
                case XdmAxis.Ancestor: return Axis.ANCESTOR;
                case XdmAxis.AncestorOrSelf: return Axis.ANCESTOR_OR_SELF;
                case XdmAxis.Attribute: return Axis.ATTRIBUTE;
                case XdmAxis.Child: return Axis.CHILD;
                case XdmAxis.Descendant: return Axis.DESCENDANT;
                case XdmAxis.DescendantOrSelf: return Axis.DESCENDANT_OR_SELF;
                case XdmAxis.Following: return Axis.FOLLOWING;
                case XdmAxis.FollowingSibling: return Axis.FOLLOWING_SIBLING;
                case XdmAxis.Namespace: return Axis.NAMESPACE;
                case XdmAxis.Parent: return Axis.PARENT;
                case XdmAxis.Preceding: return Axis.PRECEDING;
                case XdmAxis.PrecedingSibling: return Axis.PRECEDING_SIBLING;
                case XdmAxis.Self: return Axis.SELF;
            }
            return 0;
        }

        /// 
        /// The Base URI of the node.
        /// 

        public Uri BaseUri {
            get { return new Uri(((NodeInfo)value).getBaseURI()); }
        }

        /// 
        /// Send the node (that is, the subtree rooted at this node) to an XmlTextWriter
        /// 
        /// 
        /// Note that a XmlTextWriter can only handle a well-formed XML document. This method
        /// will therefore signal an exception if the node is a document node with no children, or with
        /// more than one element child.
        /// 

        public void WriteTo(XmlTextWriter writer) {
            NodeInfo node = ((NodeInfo)value);
            DotNetReceiver receiver = new DotNetReceiver(writer);
            receiver.setPipelineConfiguration(node.getConfiguration().makePipelineConfiguration());
            receiver.open();
            node.copy(receiver, 2, false, 0);
            receiver.close();
        }

        /// 
        /// Return a serialization of this node as lexical XML
        /// 
        /// 
        /// In the case of an element node, the result will be a well-formed
        /// XML document serialized as defined in the W3C XSLT/XQuery serialization specification,
        /// using options method="xml", indent="yes", omit-xml-declaration="yes".
        /// In the case of a document node, the result will be a well-formed
        /// XML document provided that the document node contains exactly one element child,
        /// and no text node children. In other cases it will be a well-formed external
        /// general parsed entity.
        /// In the case of an attribute node, the output is a string in the form
        /// name="value". The name will use the original namespace prefix.
        /// Other nodes, such as text nodes, comments, and processing instructions, are
        /// represented as they would appear in lexical XML.
        /// 

        public String OuterXml {
            get {
                NodeInfo node = ((NodeInfo)value);

                if (node.getNodeKind() == JType.ATTRIBUTE) {
                    String val = node.getStringValue().Replace("\"", """);
                    val = val.Replace("<", "<");
                    val = val.Replace("&", "&");
                    return node.getDisplayName() + "=\"" + val + '"';
                }

                Serializer serializer = new Serializer();
                serializer.SetOutputProperty(Serializer.METHOD, "xml");
                serializer.SetOutputProperty(Serializer.INDENT, "yes");
                serializer.SetOutputProperty(Serializer.OMIT_XML_DECLARATION, "yes");

                StringWriter sw = new StringWriter();
                serializer.SetOutputWriter(sw);
                node.copy(serializer.GetReceiver(node.getConfiguration()), 2, false, 0);
                return sw.ToString();
            }
        }


        /// 
        /// Return a string representation of the node.
        /// 
        /// 
        /// This currently returns the same as the OuterXml property.
        /// To get the string value as defined in XPath, use the StringValue property.
        /// 

        public override String ToString() {
            return OuterXml;
        }

        /// 
        /// Escape hatch to the underlying class in the Java implementation
        /// 

        public NodeInfo Implementation {
            get { return ((NodeInfo)value); }
        }


    }


    /// 
    /// The class XdmEmptySequence represents an empty sequence in the XDM Data Model.
    /// 
    /// 
    /// An empty sequence may also be represented by an XdmValue whose length
    /// happens to be zero. Applications should therefore not test to see whether an object
    /// is an instance of this class in order to decide whether it is empty.
    /// In interfaces that expect an XdmItem, an empty sequence is represented
    /// by a CLI null value. 
    /// 

    [Serializable]
    public sealed class XdmEmptySequence : XdmValue {

        ///The singular instance of this class

        public static XdmEmptySequence INSTANCE = new XdmEmptySequence();

        private XdmEmptySequence() {
            this.value = null;
        }
    }


    /// 
    /// The QName class represents an instance of xs:QName, as defined in the XPath 2.0
    /// data model. Internally, it has three components, a namespace URI, a local name, and
    /// a prefix. The prefix is intended to be used only when converting the value back to 
    /// a string.
    /// 
    /// 
    /// Note that a QName is not itself an XdmItem in this model; however it can
    /// be wrapped in an XdmItem.
    ///     

    [Serializable]
    public sealed class QName {

        private String prefix;
        private String uri;
        private String local;
        int hashcode = -1;      // evaluated lazily
        int fingerprint = -1;   // evaluated only if the QName is registered with the Processor
        private NamePool pool = null;

        private static String XS = NamespaceConstant.SCHEMA;

        /// QName constant for the name xs:string
        public static readonly QName XS_STRING = new QName(XS, "xs:string");

        /// QName constant for the name xs:integer
        public static readonly QName XS_INTEGER = new QName(XS, "xs:integer");

        /// QName constant for the name xs:double
        public static readonly QName XS_DOUBLE = new QName(XS, "xs:double");

        /// QName constant for the name xs:float
        public static readonly QName XS_FLOAT = new QName(XS, "xs:float");

        /// QName constant for the name xs:decimal
        public static readonly QName XS_DECIMAL = new QName(XS, "xs:decimal");

        /// QName constant for the name xs:boolean
        public static readonly QName XS_BOOLEAN = new QName(XS, "xs:boolean");

        /// QName constant for the name xs:anyURI
        public static readonly QName XS_ANYURI = new QName(XS, "xs:anyURI");

        /// QName constant for the name xs:QName
        public static readonly QName XS_QNAME = new QName(XS, "xs:QName");

        /// QName constant for the name xs:untypedAtomic
        public static readonly QName XS_UNTYPED_ATOMIC = new QName(XS, "xdt:untypedAtomic");

        /// QName constant for the name xs:untypedAtomic (for backwards compatibility)
        public static readonly QName XDT_UNTYPED_ATOMIC = new QName(XS, "xdt:untypedAtomic");

        /// 
        /// Construct a QName using a namespace URI and a lexical representation.
        /// The lexical representation may be a local name on its own, or it may 
        /// be in the form prefix:local-name
        /// 
        /// 
        /// This constructor does not check that the components of the QName are
        /// lexically valid.
        /// 
        /// The namespace URI. Use either the string "" or null
        /// for names that are not in any namespace.
        /// 
        /// Either the local part of the name, or the prefix
        /// and local part in the format prefix:local
        /// 

        public QName(String uri, String lexical) {
            // TODO: check for validity
            this.uri = (uri == null ? "" : uri);
            int colon = lexical.IndexOf(':');
            if (colon < 0) {
                this.prefix = "";
                this.local = lexical;
            } else {
                this.prefix = lexical.Substring(0, colon);
                this.local = lexical.Substring(colon + 1);
            }
        }

        /// 
        /// Construct a QName using a namespace prefix, a namespace URI, and a local name
        /// (in that order).
        /// 
        /// 
        /// This constructor does not check that the components of the QName are
        /// lexically valid.
        /// 
        /// The prefix of the name. Use either the string ""
        /// or null for names that have no prefix (that is, they are in the default
        /// namespace)
        /// The namespace URI. Use either the string "" or null
        /// for names that are not in any namespace.
        /// 
        /// The local part of the name

        public QName(String prefix, String uri, String local) {
            this.uri = (uri == null ? String.Empty : uri);
            this.local = local;
            this.prefix = (prefix == null ? String.Empty : prefix);
        }

        /// 
        /// Construct a QName from a lexical QName, supplying an element node whose
        /// in-scope namespaces are to be used to resolve any prefix contained in the QName.
        /// 
        /// 
        /// This constructor checks that the components of the QName are
        /// lexically valid.
        /// If the lexical QName has no prefix, the name is considered to be in the
        /// default namespace, as defined by xmlns="...".
        /// If the prefix of the lexical QName is not in scope, returns null.
        /// 
        /// The lexical QName, in the form prefix:local
        /// or simply local.
        /// The element node whose in-scope namespaces are to be used
        /// to resolve the prefix part of the lexical QName.
        /// If the prefix of the lexical QName is not in scope
        /// If the lexical QName is invalid 
        /// (for example, if it contains invalid characters)
        /// 

        public QName(String lexicalQName, XdmNode element) {
            try {
                NodeInfo node = (NodeInfo)element.value;
                NamePool pool = node.getConfiguration().getNamePool();
                int nc = pool.allocateLexicalQName(lexicalQName, true, new InscopeNamespaceResolver(node),
                    node.getConfiguration().getNameChecker());
                this.uri = pool.getURI(nc);
                this.local = pool.getLocalName(nc);
                this.prefix = pool.getPrefix(nc);
            } catch (net.sf.saxon.trans.XPathException err) {
                throw new ArgumentException(err.getMessage());
            }
        }

        /// 
        /// Construct a QName from an XmlQualifiedName (as defined in the
        /// System.Xml package).
        /// 
        /// 
        /// Note that an XmlQualifiedName does not contain any prefix, so the result
        /// will always have a prefix of ""
        /// 
        /// The XmlQualifiedName

        public QName(XmlQualifiedName qualifiedName) {
            this.uri = qualifiedName.Namespace;
            this.local = qualifiedName.Name;
            this.prefix = String.Empty;
        }

        //  internal constructor from a QNameValue

        internal QName(QNameValue q) {
            this.uri = q.getNamespaceURI();
            this.prefix = q.getPrefix();
            this.local = q.getLocalName();
        }

        /// 
        /// Factory method to construct a QName from a string containing the expanded
        /// QName in Clark notation, that is, {uri}local
        /// 
        /// 
        /// The prefix part of the QName will be set to an empty string.
        /// 
        /// The URI in Clark notation: {uri}local if the
        /// name is in a namespace, or simply local if not. 

        public static QName FromClarkName(String expandedName) {
            String namespaceURI;
            String localName;
            if (expandedName[0] == '{') {
                int closeBrace = expandedName.IndexOf('}');
                if (closeBrace < 0) {
                    throw new ArgumentException("No closing '}' in Clark name");
                }
                namespaceURI = expandedName.Substring(1, closeBrace - 1);
                if (closeBrace == expandedName.Length) {
                    throw new ArgumentException("Missing local part in Clark name");
                }
                localName = expandedName.Substring(closeBrace + 1);
            } else {
                namespaceURI = "";
                localName = expandedName;
            }

            return new QName("", namespaceURI, localName);
        }

        /// 
        /// Register a QName with the Processor. This makes comparison faster
        /// when the QName is compared with others that are also registered with the Processor.
        /// 
        /// The Processor in which the name is to be registered.

        public void Register(Processor processor) {
            pool = processor.config.getNamePool();
            fingerprint = pool.allocate(prefix, uri, local) & 0xfffff;
        }

        /// 
        /// Validate the QName against the XML 1.0 or XML 1.1 rules for valid names.
        /// 
        /// The Processor in which the name is to be validated.
        /// This determines whether the XML 1.0 or XML 1.1 rules for forming names are used.
        /// true if the name is valid, false if not

        public bool IsValid(Processor processor) {
            NameChecker nc = processor.config.getNameChecker();
            if (prefix != String.Empty) {
                if (!nc.isValidNCName(prefix)) {
                    return false;
                }
            }
            if (!nc.isValidNCName(local)) {
                return false;
            }
            return true;
        }

        /// The prefix of the QName. This plays no role in operations such as comparison
        /// of QNames for equality, but is retained (as specified in XPath) so that a string representation
        /// can be reconstructed.
        /// 
        /// 
        /// Returns the zero-length string in the case of a QName that has no prefix.
        /// 

        public String Prefix {
            get { return prefix; }
        }

        /// The namespace URI of the QName. Returns "" (the zero-length string) if the
        /// QName is not in a namespace.
        /// 

        public String Uri {
            get { return uri; }
        }

        /// The local part of the QName

        public String LocalName {
            get { return local; }
        }

        /// The expanded name, as a string using the notation devised by James Clark.
        /// If the name is in a namespace, the resulting string takes the form {uri}local.
        /// Otherwise, the value is the local part of the name.
        /// 

        public String ClarkName {
            get {
                if (uri == "") {
                    return local;
                } else {
                    return "{" + uri + "}" + local;
                }
            }
        }

        /// 
        /// Convert the value to a string. The resulting string is the lexical form of the QName,
        /// using the original prefix if there was one.
        /// 

        public override String ToString() {
            if (prefix == "") {
                return local;
            } else {
                return prefix + ":" + uri;
            }
        }

        /// 
        /// Get a hash code for the QName, to support equality matching. This supports the
        /// semantics of equality, which considers only the namespace URI and local name, and
        /// not the prefix.
        /// 
        /// 
        /// The algorithm for allocating a hash code does not depend on registering the QName 
        /// with the Processor.
        /// 

        public override int GetHashCode() {
            if (hashcode == -1) {
                hashcode = ClarkName.GetHashCode();
            }
            return hashcode;
        }

        /// 
        /// Test whether two QNames are equal. This supports the
        /// semantics of equality, which considers only the namespace URI and local name, and
        /// not the prefix.
        /// 
        /// 
        /// The result of the function does not depend on registering the QName 
        /// with the Processor, but is computed more quickly if the QNames have
        /// both been registered
        /// 

        public override bool Equals(Object other) {
            if (!(other is QName)) {
                return false;
            }
            if (pool != null && pool == ((QName)other).pool) {
                return fingerprint == ((QName)other).fingerprint;
            }
            if (GetHashCode() != ((QName)other).GetHashCode()) {
                return false;
            }
            return ClarkName == ((QName)other).ClarkName;
            //TODO: avoid computing ClarkName more than once
        }

        /// 
        /// Convert the value to an XmlQualifiedName (as defined in the
        /// System.Xml package)
        /// 
        /// 
        /// Note that this loses the prefix.
        /// 

        public XmlQualifiedName ToXmlQualifiedName() {
            return new XmlQualifiedName(local, uri);
        }

        /// 
        /// Convert to a net.sf.saxon.value.QNameValue
        /// 

        internal QNameValue ToQNameValue() {
            return new QNameValue(prefix, uri, local, null);
        }


    }

    /// 
    /// This class represents an enumeration of the values in an XPath
    /// sequence. It implements the IEnumerator interface, and the objects
    /// returned are always instances of XPathItem
    /// 
    /// 
    /// Because the underlying value can be evaluated lazily, it is possible
    /// for exceptions to occur as the sequence is being read.
    /// 

    [Serializable]
    public class SequenceEnumerator : IEnumerator {

        private SequenceIterator iter;

        internal SequenceEnumerator(SequenceIterator iter) {
            this.iter = iter;
        }

        /// Return the current item in the sequence
        /// An object which will always be an instance of XdmItem

        public object Current {
            get { return XdmValue.Wrap(iter.current()); }
        }

        /// Move to the next item in the sequence
        /// true if there are more items in the sequence

        public bool MoveNext() {
            return (iter.next() != null);
        }

        /// Reset the enumeration so that the next call of
        /// MoveNext will position the enumeration at the
        /// first item in the sequence

        public void Reset() {
            iter = iter.getAnother();
        }
    }

    /// 
    /// Enumeration identifying the thirteen XPath axes
    /// 

    public enum XdmAxis {
        /// The XPath ancestor axis 
        Ancestor,
        /// The XPath ancestor-or-self axis 
        AncestorOrSelf,
        /// The XPath attribute axis 
        Attribute,
        /// The XPath child axis 
        Child,
        /// The XPath descendant axis 
        Descendant,
        /// The XPath descandant-or-self axis 
        DescendantOrSelf,
        /// The XPath following axis 
        Following,
        /// The XPath following-sibling axis 
        FollowingSibling,
        /// The XPath namespace axis 
        Namespace,
        /// The XPath parent axis 
        Parent,
        /// The XPath preceding axis 
        Preceding,
        /// The XPath preceding-sibling axis 
        PrecedingSibling,
        /// The XPath self axis 
        Self
    }

    internal class EmptyEnumerator : IEnumerator {

        public static EmptyEnumerator INSTANCE = new EmptyEnumerator();

        private EmptyEnumerator() { }

        public void Reset() { }

        public object Current {
            get { throw new InvalidOperationException("Collection is empty."); }
        }

        public bool MoveNext() {
            return false;
        }
    }


}

//
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
// you may not use this file except in compliance with the License. You may obtain a copy of the
// License at http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations under the License.
//
// The Original Code is: all this file.
//
// The Initial Developer of the Original Code is Michael H. Kay.
//
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
//
// Contributor(s): none.
//




© 2015 - 2024 Weber Informatics LLC | Privacy Policy