/// <summary>
        /// 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.
        /// </summary>
        /// <param name="schemaNS">the root namespace</param>
        /// <param name="pos">the parsing position helper</param>
        /// <param name="expandedXPath">the path to contribute to</param>
        /// <exception cref="Com.Adobe.Xmp.XMPException">If the path is not valid.</exception>
        private 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", XMPErrorConstants.Badxpath);
            }
            string       rootProp  = VerifyXPathRoot(schemaNS, Sharpen.Runtime.Substring(pos.path, pos.stepBegin, pos.stepEnd));
            XMPAliasInfo aliasInfo = XMPMetaFactory.GetSchemaRegistry().FindAlias(rootProp);

            if (aliasInfo == null)
            {
                // add schema xpath step
                expandedXPath.Add(new XMPPathSegment(schemaNS, XMPPath.SchemaNode));
                XMPPathSegment rootStep = new XMPPathSegment(rootProp, XMPPath.StructFieldStep);
                expandedXPath.Add(rootStep);
            }
            else
            {
                // add schema xpath step and base step of alias
                expandedXPath.Add(new XMPPathSegment(aliasInfo.GetNamespace(), XMPPath.SchemaNode));
                XMPPathSegment rootStep = new XMPPathSegment(VerifyXPathRoot(aliasInfo.GetNamespace(), aliasInfo.GetPropName()), XMPPath.StructFieldStep);
                rootStep.SetAlias(true);
                rootStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
                expandedXPath.Add(rootStep);
                if (aliasInfo.GetAliasForm().IsArrayAltText())
                {
                    XMPPathSegment qualSelectorStep = new XMPPathSegment("[?xml:lang='x-default']", XMPPath.QualSelectorStep);
                    qualSelectorStep.SetAlias(true);
                    qualSelectorStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
                    expandedXPath.Add(qualSelectorStep);
                }
                else
                {
                    if (aliasInfo.GetAliasForm().IsArray())
                    {
                        XMPPathSegment indexStep = new XMPPathSegment("[1]", XMPPath.ArrayIndexStep);
                        indexStep.SetAlias(true);
                        indexStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
                        expandedXPath.Add(indexStep);
                    }
                }
            }
        }
        /// <summary>Parses a struct segment</summary>
        /// <param name="pos">the current position in the path</param>
        /// <returns>Retusn the segment or an errror</returns>
        /// <exception cref="Com.Adobe.Xmp.XMPException">If the sement is empty</exception>
        private static XMPPathSegment ParseStructSegment(PathPosition pos)
        {
            pos.nameStart = pos.stepBegin;
            while (pos.stepEnd < pos.path.Length && "/[*".IndexOf(pos.path[pos.stepEnd]) < 0)
            {
                pos.stepEnd++;
            }
            pos.nameEnd = pos.stepEnd;
            if (pos.stepEnd == pos.stepBegin)
            {
                throw new XMPException("Empty XMPPath segment", XMPErrorConstants.Badxpath);
            }
            // ! Touch up later, also changing '@' to '?'.
            XMPPathSegment segment = new XMPPathSegment(Sharpen.Runtime.Substring(pos.path, pos.stepBegin, pos.stepEnd), XMPPath.StructFieldStep);

            return(segment);
        }
        /// <summary>Parses an array index segment.</summary>
        /// <param name="pos">the xmp path</param>
        /// <returns>Returns the segment or an error</returns>
        /// <exception cref="Com.Adobe.Xmp.XMPException">thrown on xmp path errors</exception>
        private static XMPPathSegment ParseIndexSegment(PathPosition pos)
        {
            XMPPathSegment segment;

            pos.stepEnd++;
            // Look at the character after the leading '['.
            if ('0' <= pos.path[pos.stepEnd] && pos.path[pos.stepEnd] <= '9')
            {
                // A numeric (decimal integer) array index.
                while (pos.stepEnd < pos.path.Length && '0' <= pos.path[pos.stepEnd] && pos.path[pos.stepEnd] <= '9')
                {
                    pos.stepEnd++;
                }
                segment = new XMPPathSegment(null, XMPPath.ArrayIndexStep);
            }
            else
            {
                // Could be "[last()]" or one of the selector forms. Find the ']' or '='.
                while (pos.stepEnd < pos.path.Length && pos.path[pos.stepEnd] != ']' && pos.path[pos.stepEnd] != '=')
                {
                    pos.stepEnd++;
                }
                if (pos.stepEnd >= pos.path.Length)
                {
                    throw new XMPException("Missing ']' or '=' for array index", XMPErrorConstants.Badxpath);
                }
                if (pos.path[pos.stepEnd] == ']')
                {
                    if (!"[last()".Equals(Sharpen.Runtime.Substring(pos.path, pos.stepBegin, pos.stepEnd)))
                    {
                        throw new XMPException("Invalid non-numeric array index", XMPErrorConstants.Badxpath);
                    }
                    segment = new XMPPathSegment(null, XMPPath.ArrayLastStep);
                }
                else
                {
                    pos.nameStart = pos.stepBegin + 1;
                    pos.nameEnd   = pos.stepEnd;
                    pos.stepEnd++;
                    // Absorb the '=', remember the quote.
                    char quote = pos.path[pos.stepEnd];
                    if (quote != '\'' && quote != '"')
                    {
                        throw new XMPException("Invalid quote in array selector", XMPErrorConstants.Badxpath);
                    }
                    pos.stepEnd++;
                    // Absorb the leading quote.
                    while (pos.stepEnd < pos.path.Length)
                    {
                        if (pos.path[pos.stepEnd] == quote)
                        {
                            // check for escaped quote
                            if (pos.stepEnd + 1 >= pos.path.Length || pos.path[pos.stepEnd + 1] != quote)
                            {
                                break;
                            }
                            pos.stepEnd++;
                        }
                        pos.stepEnd++;
                    }
                    if (pos.stepEnd >= pos.path.Length)
                    {
                        throw new XMPException("No terminating quote for array selector", XMPErrorConstants.Badxpath);
                    }
                    pos.stepEnd++;
                    // Absorb the trailing quote.
                    // ! Touch up later, also changing '@' to '?'.
                    segment = new XMPPathSegment(null, XMPPath.FieldSelectorStep);
                }
            }
            if (pos.stepEnd >= pos.path.Length || pos.path[pos.stepEnd] != ']')
            {
                throw new XMPException("Missing ']' for array index", XMPErrorConstants.Badxpath);
            }
            pos.stepEnd++;
            segment.SetName(Sharpen.Runtime.Substring(pos.path, pos.stepBegin, pos.stepEnd));
            return(segment);
        }
 /// <summary>
 /// After processing by ExpandXPath, a step can be of these forms:
 /// <ul>
 /// <li>qualName - A top level property or struct field.
 /// </summary>
 /// <remarks>
 /// After processing by ExpandXPath, a step can be of these forms:
 /// <ul>
 /// <li>qualName - A top level property or struct field.
 /// <li>[index] - An element of an array.
 /// <li>[last()] - The last element of an array.
 /// <li>[qualName="value"] - An element in an array of structs, chosen by a field value.
 /// <li>[?qualName="value"] - An element in an array, chosen by a qualifier value.
 /// <li>?qualName - A general qualifier.
 /// </ul>
 /// Find the appropriate child node, resolving aliases, and optionally creating nodes.
 /// </remarks>
 /// <param name="parentNode">the node to start to start from</param>
 /// <param name="nextStep">the xpath segment</param>
 /// <param name="createNodes"></param>
 /// <returns>returns the found or created XMPPath node</returns>
 /// <exception cref="Com.Adobe.Xmp.XMPException"></exception>
 private static XMPNode FollowXPathStep(XMPNode parentNode, XMPPathSegment nextStep, bool createNodes)
 {
     XMPNode nextNode = null;
     int index = 0;
     int stepKind = nextStep.GetKind();
     if (stepKind == XMPPath.StructFieldStep)
     {
         nextNode = FindChildNode(parentNode, nextStep.GetName(), createNodes);
     }
     else
     {
         if (stepKind == XMPPath.QualifierStep)
         {
             nextNode = FindQualifierNode(parentNode, Sharpen.Runtime.Substring(nextStep.GetName(), 1), createNodes);
         }
         else
         {
             // This is an array indexing step. First get the index, then get the node.
             if (!parentNode.GetOptions().IsArray())
             {
                 throw new XMPException("Indexing applied to non-array", XMPErrorConstants.Badxpath);
             }
             if (stepKind == XMPPath.ArrayIndexStep)
             {
                 index = FindIndexedItem(parentNode, nextStep.GetName(), createNodes);
             }
             else
             {
                 if (stepKind == XMPPath.ArrayLastStep)
                 {
                     index = parentNode.GetChildrenLength();
                 }
                 else
                 {
                     if (stepKind == XMPPath.FieldSelectorStep)
                     {
                         string[] result = Utils.SplitNameAndValue(nextStep.GetName());
                         string fieldName = result[0];
                         string fieldValue = result[1];
                         index = LookupFieldSelector(parentNode, fieldName, fieldValue);
                     }
                     else
                     {
                         if (stepKind == XMPPath.QualSelectorStep)
                         {
                             string[] result = Utils.SplitNameAndValue(nextStep.GetName());
                             string qualName = result[0];
                             string qualValue = result[1];
                             index = LookupQualSelector(parentNode, qualName, qualValue, nextStep.GetAliasForm());
                         }
                         else
                         {
                             throw new XMPException("Unknown array indexing step in FollowXPathStep", XMPErrorConstants.Internalfailure);
                         }
                     }
                 }
             }
             if (1 <= index && index <= parentNode.GetChildrenLength())
             {
                 nextNode = parentNode.GetChild(index);
             }
         }
     }
     return nextNode;
 }
示例#5
0
 // Bits for XPathStepInfo options.
 //
 /// <summary>Append a path segment</summary>
 /// <param name="segment">the segment to add</param>
 public virtual void Add(XMPPathSegment segment)
 {
     segments.Add(segment);
 }
示例#6
0
		// Bits for XPathStepInfo options.
		// 
		/// <summary>Append a path segment</summary>
		/// <param name="segment">the segment to add</param>
		public virtual void Add(XMPPathSegment segment)
		{
			segments.Add(segment);
		}
		/// <summary>
		/// 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.
		/// </summary>
		/// <param name="schemaNS">the root namespace</param>
		/// <param name="pos">the parsing position helper</param>
		/// <param name="expandedXPath">the path to contribute to</param>
		/// <exception cref="Com.Adobe.Xmp.XMPException">If the path is not valid.</exception>
		private 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", XMPErrorConstants.Badxpath);
			}
			string rootProp = VerifyXPathRoot(schemaNS, Sharpen.Runtime.Substring(pos.path, pos.stepBegin, pos.stepEnd));
			XMPAliasInfo aliasInfo = XMPMetaFactory.GetSchemaRegistry().FindAlias(rootProp);
			if (aliasInfo == null)
			{
				// add schema xpath step
				expandedXPath.Add(new XMPPathSegment(schemaNS, XMPPath.SchemaNode));
				XMPPathSegment rootStep = new XMPPathSegment(rootProp, XMPPath.StructFieldStep);
				expandedXPath.Add(rootStep);
			}
			else
			{
				// add schema xpath step and base step of alias
				expandedXPath.Add(new XMPPathSegment(aliasInfo.GetNamespace(), XMPPath.SchemaNode));
				XMPPathSegment rootStep = new XMPPathSegment(VerifyXPathRoot(aliasInfo.GetNamespace(), aliasInfo.GetPropName()), XMPPath.StructFieldStep);
				rootStep.SetAlias(true);
				rootStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
				expandedXPath.Add(rootStep);
				if (aliasInfo.GetAliasForm().IsArrayAltText())
				{
					XMPPathSegment qualSelectorStep = new XMPPathSegment("[?xml:lang='x-default']", XMPPath.QualSelectorStep);
					qualSelectorStep.SetAlias(true);
					qualSelectorStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
					expandedXPath.Add(qualSelectorStep);
				}
				else
				{
					if (aliasInfo.GetAliasForm().IsArray())
					{
						XMPPathSegment indexStep = new XMPPathSegment("[1]", XMPPath.ArrayIndexStep);
						indexStep.SetAlias(true);
						indexStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
						expandedXPath.Add(indexStep);
					}
				}
			}
		}
		/// <summary>Parses an array index segment.</summary>
		/// <param name="pos">the xmp path</param>
		/// <returns>Returns the segment or an error</returns>
		/// <exception cref="Com.Adobe.Xmp.XMPException">thrown on xmp path errors</exception>
		private static XMPPathSegment ParseIndexSegment(PathPosition pos)
		{
			XMPPathSegment segment;
			pos.stepEnd++;
			// Look at the character after the leading '['.
			if ('0' <= pos.path[pos.stepEnd] && pos.path[pos.stepEnd] <= '9')
			{
				// A numeric (decimal integer) array index.
				while (pos.stepEnd < pos.path.Length && '0' <= pos.path[pos.stepEnd] && pos.path[pos.stepEnd] <= '9')
				{
					pos.stepEnd++;
				}
				segment = new XMPPathSegment(null, XMPPath.ArrayIndexStep);
			}
			else
			{
				// Could be "[last()]" or one of the selector forms. Find the ']' or '='.
				while (pos.stepEnd < pos.path.Length && pos.path[pos.stepEnd] != ']' && pos.path[pos.stepEnd] != '=')
				{
					pos.stepEnd++;
				}
				if (pos.stepEnd >= pos.path.Length)
				{
					throw new XMPException("Missing ']' or '=' for array index", XMPErrorConstants.Badxpath);
				}
				if (pos.path[pos.stepEnd] == ']')
				{
					if (!"[last()".Equals(Sharpen.Runtime.Substring(pos.path, pos.stepBegin, pos.stepEnd)))
					{
						throw new XMPException("Invalid non-numeric array index", XMPErrorConstants.Badxpath);
					}
					segment = new XMPPathSegment(null, XMPPath.ArrayLastStep);
				}
				else
				{
					pos.nameStart = pos.stepBegin + 1;
					pos.nameEnd = pos.stepEnd;
					pos.stepEnd++;
					// Absorb the '=', remember the quote.
					char quote = pos.path[pos.stepEnd];
					if (quote != '\'' && quote != '"')
					{
						throw new XMPException("Invalid quote in array selector", XMPErrorConstants.Badxpath);
					}
					pos.stepEnd++;
					// Absorb the leading quote.
					while (pos.stepEnd < pos.path.Length)
					{
						if (pos.path[pos.stepEnd] == quote)
						{
							// check for escaped quote
							if (pos.stepEnd + 1 >= pos.path.Length || pos.path[pos.stepEnd + 1] != quote)
							{
								break;
							}
							pos.stepEnd++;
						}
						pos.stepEnd++;
					}
					if (pos.stepEnd >= pos.path.Length)
					{
						throw new XMPException("No terminating quote for array selector", XMPErrorConstants.Badxpath);
					}
					pos.stepEnd++;
					// Absorb the trailing quote.
					// ! Touch up later, also changing '@' to '?'.
					segment = new XMPPathSegment(null, XMPPath.FieldSelectorStep);
				}
			}
			if (pos.stepEnd >= pos.path.Length || pos.path[pos.stepEnd] != ']')
			{
				throw new XMPException("Missing ']' for array index", XMPErrorConstants.Badxpath);
			}
			pos.stepEnd++;
			segment.SetName(Sharpen.Runtime.Substring(pos.path, pos.stepBegin, pos.stepEnd));
			return segment;
		}
		/// <summary>Parses a struct segment</summary>
		/// <param name="pos">the current position in the path</param>
		/// <returns>Retusn the segment or an errror</returns>
		/// <exception cref="Com.Adobe.Xmp.XMPException">If the sement is empty</exception>
		private static XMPPathSegment ParseStructSegment(PathPosition pos)
		{
			pos.nameStart = pos.stepBegin;
			while (pos.stepEnd < pos.path.Length && "/[*".IndexOf(pos.path[pos.stepEnd]) < 0)
			{
				pos.stepEnd++;
			}
			pos.nameEnd = pos.stepEnd;
			if (pos.stepEnd == pos.stepBegin)
			{
				throw new XMPException("Empty XMPPath segment", XMPErrorConstants.Badxpath);
			}
			// ! Touch up later, also changing '@' to '?'.
			XMPPathSegment segment = new XMPPathSegment(Sharpen.Runtime.Substring(pos.path, pos.stepBegin, pos.stepEnd), XMPPath.StructFieldStep);
			return segment;
		}