Ejemplo n.º 1
0
 /// <summary>Constructor with optional initial values.</summary>
 /// <remarks>If <c>propName</c> is provided, <c>schemaNS</c> has also be provided.</remarks>
 /// <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 reduced to this property within the <c>schemaNS</c></param>
 /// <param name="options">advanced iteration options, see <see cref="IteratorOptions"/></param>
 /// <exception cref="XmpException">If the node defined by the parameters is not existing.</exception>
 public XmpIterator(XmpMeta 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 = null;
     string initialPath = null;
     var baseSchema = !string.IsNullOrEmpty(schemaNs);
     var baseProperty = !string.IsNullOrEmpty(propPath);
     if (!baseSchema && !baseProperty)
     {
         // complete tree will be iterated
         startNode = xmp.GetRoot();
     }
     else
     {
         if (baseSchema && baseProperty)
         {
             // Schema and property node provided
             var path = XmpPathParser.ExpandXPath(schemaNs, propPath);
             // base path is the prop path without the property leaf
             var basePath = new XmpPath();
             for (var i = 0; i < path.Size() - 1; i++)
             {
                 basePath.Add(path.GetSegment(i));
             }
             startNode = XmpNodeUtils.FindNode(xmp.GetRoot(), path, false, null);
             BaseNamespace = schemaNs;
             initialPath = basePath.ToString();
         }
         else
         {
             if (baseSchema && !baseProperty)
             {
                 // Only Schema provided
                 startNode = XmpNodeUtils.FindSchemaNode(xmp.GetRoot(), schemaNs, false);
             }
             else
             {
                 // !baseSchema  &&  baseProperty
                 // No schema but property provided -> error
                 throw new XmpException("Schema namespace URI is required", XmpErrorCode.BadSchema);
             }
         }
     }
     // create iterator
     _nodeIterator = startNode != null
         ? (IIterator)(!Options.IsJustChildren
             ? new NodeIterator(this, startNode, initialPath, 1)
             : new NodeIteratorChildren(this, startNode, initialPath))
         : Enumerable.Empty<object>().Iterator();
 }
Ejemplo n.º 2
0
 /// <summary>Follow an expanded path expression to find or create a node.</summary>
 /// <param name="xmpTree">the node to begin the search.</param>
 /// <param name="xpath">the complete xpath</param>
 /// <param name="createNodes">
 /// flag if nodes shall be created
 /// (when called by <c>setProperty()</c>)
 /// </param>
 /// <param name="leafOptions">
 /// the options for the created leaf nodes (only when
 /// <c>createNodes == true</c>).
 /// </param>
 /// <returns>Returns the node if found or created or <c>null</c>.</returns>
 /// <exception cref="XmpException">
 /// An exception is only thrown if an error occurred,
 /// not if a node was not found.
 /// </exception>
 internal static XmpNode FindNode(XmpNode xmpTree, XmpPath xpath, bool createNodes, PropertyOptions leafOptions)
 {
     // check if xpath is set.
     if (xpath == null || xpath.Size() == 0)
     {
         throw new XmpException("Empty XMPPath", XmpErrorCode.BadXPath);
     }
     // Root of implicitly created subtree to possible delete it later.
     // Valid only if leaf is new.
     XmpNode rootImplicitNode = null;
     XmpNode currNode = null;
     // resolve schema step
     currNode = FindSchemaNode(xmpTree, xpath.GetSegment(XmpPath.StepSchema).Name, createNodes);
     if (currNode == null)
     {
         return null;
     }
     if (currNode.IsImplicit)
     {
         currNode.IsImplicit = false;
         // Clear the implicit node bit.
         rootImplicitNode = currNode;
     }
     // Save the top most implicit node.
     // Now follow the remaining steps of the original XMPPath.
     try
     {
         for (var i = 1; i < xpath.Size(); i++)
         {
             currNode = FollowXPathStep(currNode, xpath.GetSegment(i), createNodes);
             if (currNode == null)
             {
                 if (createNodes)
                 {
                     // delete implicitly created nodes
                     DeleteNode(rootImplicitNode);
                 }
                 return null;
             }
             if (currNode.IsImplicit)
             {
                 // clear the implicit node flag
                 currNode.IsImplicit = false;
                 // if node is an ALIAS (can be only in root step, auto-create array
                 // when the path has been resolved from a not simple alias type
                 if (i == 1 && xpath.GetSegment(i).IsAlias && xpath.GetSegment(i).AliasForm != 0)
                 {
                     currNode.Options.SetOption(xpath.GetSegment(i).AliasForm, true);
                 }
                 else
                 {
                     // "CheckImplicitStruct" in C++
                     if (i < xpath.Size() - 1 && xpath.GetSegment(i).Kind == XmpPath.StructFieldStep && !currNode.Options.IsCompositeProperty)
                     {
                         currNode.Options.IsStruct = true;
                     }
                 }
                 if (rootImplicitNode == null)
                 {
                     rootImplicitNode = currNode;
                 }
             }
         }
     }
     catch (XmpException)
     {
         // Save the top most implicit node.
         // if new notes have been created prior to the error, delete them
         if (rootImplicitNode != null)
         {
             DeleteNode(rootImplicitNode);
         }
         throw;
     }
     if (rootImplicitNode != null)
     {
         // set options only if a node has been successful created
         currNode.Options.MergeWith(leafOptions);
         currNode.Options = currNode.Options;
     }
     return currNode;
 }