Add() public method

Append a path segment
public Add ( XmpPathSegment segment ) : void
segment XmpPathSegment the segment to add
return void
Ejemplo n.º 1
0
        /**
         * Parses the root node of an XMP Path, checks if namespace and prefix fit together
         * and resolve the property to the base property if it is an alias.
         * @param schemaNs the root namespace
         * @param pos the parsing position helper
         * @param expandedXPath  the path to contribute to
         * @throws XmpException If the path is not valid.
         */

        internal static void ParseRootNode(string schemaNs, PathPosition pos, XmpPath expandedXPath)
        {
            while (pos.StepEnd < pos.Path.Length && "/[*".IndexOf(pos.Path[pos.StepEnd]) < 0)
            {
                pos.StepEnd++;
            }

            if (pos.StepEnd == pos.StepBegin)
            {
                throw new XmpException("Empty initial XmpPath step", XmpError.BADXPATH);
            }

            string        rootProp  = VerifyXPathRoot(schemaNs, pos.Path.Substring(pos.StepBegin, pos.StepEnd - pos.StepBegin));
            IXmpAliasInfo aliasInfo = XmpMetaFactory.SchemaRegistry.FindAlias(rootProp);

            if (aliasInfo == null)
            {
                // add schema xpath step
                expandedXPath.Add(new XmpPathSegment(schemaNs, XmpPath.SCHEMA_NODE));
                XmpPathSegment rootStep = new XmpPathSegment(rootProp, XmpPath.STRUCT_FIELD_STEP);
                expandedXPath.Add(rootStep);
            }
            else
            {
                // add schema xpath step and base step of alias
                expandedXPath.Add(new XmpPathSegment(aliasInfo.Namespace, XmpPath.SCHEMA_NODE));
                XmpPathSegment rootStep = new XmpPathSegment(VerifyXPathRoot(aliasInfo.Namespace, aliasInfo.PropName),
                                                             XmpPath.STRUCT_FIELD_STEP);
                rootStep.Alias     = true;
                rootStep.AliasForm = aliasInfo.AliasForm.Options;
                expandedXPath.Add(rootStep);

                if (aliasInfo.AliasForm.ArrayAltText)
                {
                    XmpPathSegment qualSelectorStep = new XmpPathSegment("[?xml:lang='x-default']",
                                                                         XmpPath.QUAL_SELECTOR_STEP);
                    qualSelectorStep.Alias     = true;
                    qualSelectorStep.AliasForm = aliasInfo.AliasForm.Options;
                    expandedXPath.Add(qualSelectorStep);
                }
                else if (aliasInfo.AliasForm.Array)
                {
                    XmpPathSegment indexStep = new XmpPathSegment("[1]", XmpPath.ARRAY_INDEX_STEP);
                    indexStep.Alias     = true;
                    indexStep.AliasForm = aliasInfo.AliasForm.Options;
                    expandedXPath.Add(indexStep);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Constructor with optionsl initial values. If <code>propName</code> is provided, 
        /// <code>schemaNs</code> has also be provided. </summary>
        /// <param name="xmp"> the iterated metadata object. </param>
        /// <param name="schemaNs"> the iteration is reduced to this schema (optional) </param>
        /// <param name="propPath"> the iteration is redurce to this property within the <code>schemaNs</code> </param>
        /// <param name="options"> advanced iteration options, see <seealso cref="IteratorOptions"/> </param>
        /// <exception cref="XmpException"> If the node defined by the paramters is not existing.  </exception>
        public XmpIteratorImpl(XmpMetaImpl xmp, string schemaNs, string propPath, IteratorOptions options) {
            // make sure that options is defined at least with defaults
            _options = options ?? new IteratorOptions();

            // the start node of the iteration depending on the schema and property filter
            XmpNode startNode;
            string initialPath = null;
            bool baseSchema = !String.IsNullOrEmpty(schemaNs);
            bool baseProperty = !String.IsNullOrEmpty(propPath);

            if (!baseSchema && !baseProperty) {
                // complete tree will be iterated
                startNode = xmp.Root;
            }
            else if (baseSchema && baseProperty) {
                // Schema and property node provided
                XmpPath path = XmpPathParser.ExpandXPath(schemaNs, propPath);

                // base path is the prop path without the property leaf
                XmpPath basePath = new XmpPath();
                for (int i = 0; i < path.Size() - 1; i++) {
                    basePath.Add(path.GetSegment(i));
                }

                startNode = XmpNodeUtils.FindNode(xmp.Root, path, false, null);
                _baseNs = schemaNs;
                initialPath = basePath.ToString();
            }
            else if (baseSchema && !baseProperty) {
                // Only Schema provided
                startNode = XmpNodeUtils.FindSchemaNode(xmp.Root, schemaNs, false);
            }
            else // !baseSchema  &&  baseProperty
            {
                // No schema but property provided -> error
                throw new XmpException("Schema namespace URI is required", XmpError.BADSCHEMA);
            }


            // create iterator
            if (startNode != null) {
                _nodeIterator = (!_options.JustChildren)
                                    ? new NodeIterator(this, startNode, initialPath, 1)
                                    : new NodeIteratorChildren(this, startNode, initialPath);
            }
            else {
                // create null iterator
                _nodeIterator = EmptyList.GetEnumerator();
            }
        }
Ejemplo n.º 3
0
        /**
	     * Split an XmpPath expression apart at the conceptual steps, adding the
	     * root namespace prefix to the first property component. The schema URI is
	     * put in the first (0th) slot in the expanded XmpPath. Check if the top
	     * level component is an alias, but don't resolve it.
	     * <p>
	     * In the most verbose case steps are separated by '/', and each step can be
	     * of these forms:
	     * <dl>
	     * <dt>prefix:name
	     * <dd> A top level property or struct field.
	     * <dt>[index]
	     * <dd> An element of an array.
	     * <dt>[last()]
	     * <dd> The last element of an array.
	     * <dt>[fieldName=&quot;value&quot;]
	     * <dd> An element in an array of structs, chosen by a field value.
	     * <dt>[@xml:lang=&quot;value&quot;]
	     * <dd> An element in an alt-text array, chosen by the xml:lang qualifier.
	     * <dt>[?qualName=&quot;value&quot;]
	     * <dd> An element in an array, chosen by a qualifier value.
	     * <dt>@xml:lang
	     * <dd> An xml:lang qualifier.
	     * <dt>?qualName
	     * <dd> A general qualifier.
	     * </dl>
	     * <p>
	     * The logic is complicated though by shorthand for arrays, the separating
	     * '/' and leading '*' are optional. These are all equivalent: array/*[2]
	     * array/[2] array*[2] array[2] All of these are broken into the 2 steps
	     * "array" and "[2]".
	     * <p>
	     * The value portion in the array selector forms is a string quoted by '''
	     * or '"'. The value may contain any character including a doubled quoting
	     * character. The value may be empty.
	     * <p>
	     * The syntax isn't checked, but an XML name begins with a letter or '_',
	     * and contains letters, digits, '.', '-', '_', and a bunch of special
	     * non-ASCII Unicode characters. An XML qualified name is a pair of names
	     * separated by a colon.
	     * @param schemaNs
	     *            schema namespace
	     * @param path
	     *            property name
	     * @return Returns the expandet XmpPath.
	     * @throws XmpException
	     *             Thrown if the format is not correct somehow.
	     * 
	     */

        public static XmpPath ExpandXPath(string schemaNs, string path) {
            if (schemaNs == null || path == null) {
                throw new XmpException("Parameter must not be null", XmpError.BADPARAM);
            }

            XmpPath expandedXPath = new XmpPath();
            PathPosition pos = new PathPosition();
            pos.Path = path;

            // Pull out the first component and do some special processing on it: add the schema
            // namespace prefix and and see if it is an alias. The start must be a "qualName".
            ParseRootNode(schemaNs, pos, expandedXPath);

            // Now continue to process the rest of the XmpPath string.
            while (pos.StepEnd < path.Length) {
                pos.StepBegin = pos.StepEnd;

                SkipPathDelimiter(path, pos);

                pos.StepEnd = pos.StepBegin;


                XmpPathSegment segment = path[pos.StepBegin] != '[' ? ParseStructSegment(pos) : ParseIndexSegment(pos);

                if (segment.Kind == XmpPath.STRUCT_FIELD_STEP) {
                    if (segment.Name[0] == '@') {
                        segment.Name = "?" + segment.Name.Substring(1);
                        if (!"?xml:lang".Equals(segment.Name)) {
                            throw new XmpException("Only xml:lang allowed with '@'", XmpError.BADXPATH);
                        }
                    }
                    if (segment.Name[0] == '?') {
                        pos.NameStart++;
                        segment.Kind = XmpPath.QUALIFIER_STEP;
                    }

                    VerifyQualName(pos.Path.Substring(pos.NameStart, pos.NameEnd - pos.NameStart));
                }
                else if (segment.Kind == XmpPath.FIELD_SELECTOR_STEP) {
                    if (segment.Name[1] == '@') {
                        segment.Name = "[?" + segment.Name.Substring(2);
                        if (!segment.Name.StartsWith("[?xml:lang=")) {
                            throw new XmpException("Only xml:lang allowed with '@'", XmpError.BADXPATH);
                        }
                    }

                    if (segment.Name[1] == '?') {
                        pos.NameStart++;
                        segment.Kind = XmpPath.QUAL_SELECTOR_STEP;
                        VerifyQualName(pos.Path.Substring(pos.NameStart, pos.NameEnd - pos.NameStart));
                    }
                }

                expandedXPath.Add(segment);
            }
            return expandedXPath;
        }
Ejemplo n.º 4
0
        /**
	     * Parses the root node of an XMP Path, checks if namespace and prefix fit together
	     * and resolve the property to the base property if it is an alias. 
	     * @param schemaNs the root namespace
	     * @param pos the parsing position helper
	     * @param expandedXPath  the path to contribute to
	     * @throws XmpException If the path is not valid.
	     */

        internal static void ParseRootNode(string schemaNs, PathPosition pos, XmpPath expandedXPath) {
            while (pos.StepEnd < pos.Path.Length && "/[*".IndexOf(pos.Path[pos.StepEnd]) < 0) {
                pos.StepEnd++;
            }

            if (pos.StepEnd == pos.StepBegin) {
                throw new XmpException("Empty initial XmpPath step", XmpError.BADXPATH);
            }

            string rootProp = VerifyXPathRoot(schemaNs, pos.Path.Substring(pos.StepBegin, pos.StepEnd - pos.StepBegin));
            IXmpAliasInfo aliasInfo = XmpMetaFactory.SchemaRegistry.FindAlias(rootProp);
            if (aliasInfo == null) {
                // add schema xpath step
                expandedXPath.Add(new XmpPathSegment(schemaNs, XmpPath.SCHEMA_NODE));
                XmpPathSegment rootStep = new XmpPathSegment(rootProp, XmpPath.STRUCT_FIELD_STEP);
                expandedXPath.Add(rootStep);
            }
            else {
                // add schema xpath step and base step of alias
                expandedXPath.Add(new XmpPathSegment(aliasInfo.Namespace, XmpPath.SCHEMA_NODE));
                XmpPathSegment rootStep = new XmpPathSegment(VerifyXPathRoot(aliasInfo.Namespace, aliasInfo.PropName),
                                                             XmpPath.STRUCT_FIELD_STEP);
                rootStep.Alias = true;
                rootStep.AliasForm = aliasInfo.AliasForm.Options;
                expandedXPath.Add(rootStep);

                if (aliasInfo.AliasForm.ArrayAltText) {
                    XmpPathSegment qualSelectorStep = new XmpPathSegment("[?xml:lang='x-default']",
                                                                         XmpPath.QUAL_SELECTOR_STEP);
                    qualSelectorStep.Alias = true;
                    qualSelectorStep.AliasForm = aliasInfo.AliasForm.Options;
                    expandedXPath.Add(qualSelectorStep);
                }
                else if (aliasInfo.AliasForm.Array) {
                    XmpPathSegment indexStep = new XmpPathSegment("[1]", XmpPath.ARRAY_INDEX_STEP);
                    indexStep.Alias = true;
                    indexStep.AliasForm = aliasInfo.AliasForm.Options;
                    expandedXPath.Add(indexStep);
                }
            }
        }
Ejemplo n.º 5
0
        /**
         * Split an XmpPath expression apart at the conceptual steps, adding the
         * root namespace prefix to the first property component. The schema URI is
         * put in the first (0th) slot in the expanded XmpPath. Check if the top
         * level component is an alias, but don't resolve it.
         * <p>
         * In the most verbose case steps are separated by '/', and each step can be
         * of these forms:
         * <dl>
         * <dt>prefix:name
         * <dd> A top level property or struct field.
         * <dt>[index]
         * <dd> An element of an array.
         * <dt>[last()]
         * <dd> The last element of an array.
         * <dt>[fieldName=&quot;value&quot;]
         * <dd> An element in an array of structs, chosen by a field value.
         * <dt>[@xml:lang=&quot;value&quot;]
         * <dd> An element in an alt-text array, chosen by the xml:lang qualifier.
         * <dt>[?qualName=&quot;value&quot;]
         * <dd> An element in an array, chosen by a qualifier value.
         * <dt>@xml:lang
         * <dd> An xml:lang qualifier.
         * <dt>?qualName
         * <dd> A general qualifier.
         * </dl>
         * <p>
         * The logic is complicated though by shorthand for arrays, the separating
         * '/' and leading '*' are optional. These are all equivalent: array/*[2]
         * array/[2] array*[2] array[2] All of these are broken into the 2 steps
         * "array" and "[2]".
         * <p>
         * The value portion in the array selector forms is a string quoted by '''
         * or '"'. The value may contain any character including a doubled quoting
         * character. The value may be empty.
         * <p>
         * The syntax isn't checked, but an XML name begins with a letter or '_',
         * and contains letters, digits, '.', '-', '_', and a bunch of special
         * non-ASCII Unicode characters. An XML qualified name is a pair of names
         * separated by a colon.
         * @param schemaNs
         *            schema namespace
         * @param path
         *            property name
         * @return Returns the expandet XmpPath.
         * @throws XmpException
         *             Thrown if the format is not correct somehow.
         *
         */

        public static XmpPath ExpandXPath(string schemaNs, string path)
        {
            if (schemaNs == null || path == null)
            {
                throw new XmpException("Parameter must not be null", XmpError.BADPARAM);
            }

            XmpPath      expandedXPath = new XmpPath();
            PathPosition pos           = new PathPosition();

            pos.Path = path;

            // Pull out the first component and do some special processing on it: add the schema
            // namespace prefix and and see if it is an alias. The start must be a "qualName".
            ParseRootNode(schemaNs, pos, expandedXPath);

            // Now continue to process the rest of the XmpPath string.
            while (pos.StepEnd < path.Length)
            {
                pos.StepBegin = pos.StepEnd;

                SkipPathDelimiter(path, pos);

                pos.StepEnd = pos.StepBegin;


                XmpPathSegment segment = path[pos.StepBegin] != '[' ? ParseStructSegment(pos) : ParseIndexSegment(pos);

                if (segment.Kind == XmpPath.STRUCT_FIELD_STEP)
                {
                    if (segment.Name[0] == '@')
                    {
                        segment.Name = "?" + segment.Name.Substring(1);
                        if (!"?xml:lang".Equals(segment.Name))
                        {
                            throw new XmpException("Only xml:lang allowed with '@'", XmpError.BADXPATH);
                        }
                    }
                    if (segment.Name[0] == '?')
                    {
                        pos.NameStart++;
                        segment.Kind = XmpPath.QUALIFIER_STEP;
                    }

                    VerifyQualName(pos.Path.Substring(pos.NameStart, pos.NameEnd - pos.NameStart));
                }
                else if (segment.Kind == XmpPath.FIELD_SELECTOR_STEP)
                {
                    if (segment.Name[1] == '@')
                    {
                        segment.Name = "[?" + segment.Name.Substring(2);
                        if (!segment.Name.StartsWith("[?xml:lang="))
                        {
                            throw new XmpException("Only xml:lang allowed with '@'", XmpError.BADXPATH);
                        }
                    }

                    if (segment.Name[1] == '?')
                    {
                        pos.NameStart++;
                        segment.Kind = XmpPath.QUAL_SELECTOR_STEP;
                        VerifyQualName(pos.Path.Substring(pos.NameStart, pos.NameEnd - pos.NameStart));
                    }
                }

                expandedXPath.Add(segment);
            }
            return(expandedXPath);
        }