Example #1
0
        /// <summary>The outermost call is special.</summary>
        /// <remarks>
        /// The outermost call is special. The names almost certainly differ. The
        /// qualifiers (and hence options) will differ for an alias to the x-default
        /// item of a langAlt array.
        /// </remarks>
        /// <param name="aliasNode">the alias node</param>
        /// <param name="baseNode">the base node of the alias</param>
        /// <param name="outerCall">marks the outer call of the recursion</param>
        /// <exception cref="XmpException">Forwards XMP errors</exception>
        private static void CompareAliasedSubtrees(XmpNode aliasNode, XmpNode baseNode, bool outerCall)
        {
            if (baseNode.Value != aliasNode.Value || aliasNode.GetChildrenLength() != baseNode.GetChildrenLength())
            {
                throw new XmpException("Mismatch between alias and base nodes", XmpErrorCode.BadXmp);
            }
            if (!outerCall && (baseNode.Name != aliasNode.Name || !aliasNode.Options.Equals(baseNode.Options) || aliasNode.GetQualifierLength() != baseNode.GetQualifierLength()))
            {
                throw new XmpException("Mismatch between alias and base nodes", XmpErrorCode.BadXmp);
            }

            for (IIterator an = aliasNode.IterateChildren(), bn = baseNode.IterateChildren(); an.HasNext() && bn.HasNext();)
            {
                var aliasChild = (XmpNode)an.Next();
                var baseChild  = (XmpNode)bn.Next();
                CompareAliasedSubtrees(aliasChild, baseChild, false);
            }

            for (IIterator an = aliasNode.IterateQualifier(), bn1 = baseNode.IterateQualifier(); an.HasNext() && bn1.HasNext();)
            {
                var aliasQual = (XmpNode)an.Next();
                var baseQual  = (XmpNode)bn1.Next();
                CompareAliasedSubtrees(aliasQual, baseQual, false);
            }
        }
Example #2
0
            /// <summary>Prepares the next node to return if not already done.</summary>
            public virtual bool HasNext()
            {
                if (_returnProperty != null)
                {
                    // hasNext has been called before
                    return(true);
                }

                // find next node
                switch (_state)
                {
                case IterateNode:
                    return(ReportNode());

                case IterateChildren:
                    if (_childrenIterator == null)
                    {
                        _childrenIterator = _visitedNode.IterateChildren();
                    }
                    var hasNext = IterateChildrenMethod(_childrenIterator);
                    if (!hasNext && _visitedNode.HasQualifier && !_enclosing.Options.IsOmitQualifiers)
                    {
                        _state            = IterateQualifier;
                        _childrenIterator = null;
                        hasNext           = HasNext();
                    }
                    return(hasNext);
                }

                if (_childrenIterator == null)
                {
                    _childrenIterator = _visitedNode.IterateQualifier();
                }
                return(IterateChildrenMethod(_childrenIterator));
            }
Example #3
0
        /// <summary>Writes all used namespaces of the subtree in node to the output.</summary>
        /// <remarks>
        /// Writes all used namespaces of the subtree in node to the output.
        /// The subtree is recursively traversed.
        /// </remarks>
        /// <param name="node">the root node of the subtree</param>
        /// <param name="usedPrefixes">a set containing currently used prefixes</param>
        /// <param name="indent">the current indent level</param>
        /// <exception cref="System.IO.IOException">Forwards all writer exceptions.</exception>
        private void DeclareUsedNamespaces(XmpNode node, ICollection <object> usedPrefixes, int indent)
        {
            if (node.Options.IsSchemaNode)
            {
                // The schema node name is the URI, the value is the prefix.
                var prefix = node.Value.Substring(0, node.Value.Length - 1 - 0);
                DeclareNamespace(prefix, node.Name, usedPrefixes, indent);
            }
            else if (node.Options.IsStruct)
            {
                for (var it = node.IterateChildren(); it.HasNext();)
                {
                    var field = (XmpNode)it.Next();
                    DeclareNamespace(field.Name, null, usedPrefixes, indent);
                }
            }

            for (var it = node.IterateChildren(); it.HasNext();)
            {
                var child = (XmpNode)it.Next();
                DeclareUsedNamespaces(child, usedPrefixes, indent);
            }

            for (var it = node.IterateQualifier(); it.HasNext();)
            {
                var qualifier = (XmpNode)it.Next();
                DeclareNamespace(qualifier.Name, null, usedPrefixes, indent);
                DeclareUsedNamespaces(qualifier, usedPrefixes, indent);
            }
        }
Example #4
0
        /// <summary>Serializes the general qualifier.</summary>
        /// <param name="node">the root node of the subtree</param>
        /// <param name="indent">the current indent level</param>
        /// <exception cref="System.IO.IOException">Forwards all writer exceptions.</exception>
        /// <exception cref="XmpException">If qualifier and element fields are mixed.</exception>
        private void SerializeCompactRdfGeneralQualifier(int indent, XmpNode node)
        {
            // The node has general qualifiers, ones that can't be
            // attributes on a property element.
            // Emit using the qualified property pseudo-struct form. The
            // value is output by a call
            // to SerializePrettyRDFProperty with emitAsRDFValue set.

            // *** We're losing compactness in the calls to SerializePrettyRDFProperty.
            // *** Should refactor to have SerializeCompactRDFProperty that does one node.
            Write(" rdf:parseType=\"Resource\">");
            WriteNewline();
            SerializeCanonicalRdfProperty(node, false, true, indent + 1);
            for (var iq = node.IterateQualifier(); iq.HasNext();)
            {
                var qualifier = (XmpNode)iq.Next();
                SerializeCanonicalRdfProperty(qualifier, false, false, indent + 1);
            }
        }
Example #5
0
        /// <summary>Recursively handles the "value" for a node.</summary>
        /// <remarks>
        /// Recursively handles the "value" for a node. It does not matter if it is a
        /// top level property, a field of a struct, or an item of an array. The
        /// indent is that for the property element. An xml:lang qualifier is written
        /// as an attribute of the property start tag, not by itself forcing the
        /// qualified property form. The patterns below mostly ignore attribute
        /// qualifiers like xml:lang. Except for the one struct case, attribute
        /// qualifiers don't affect the output form.
        /// <code>
        /// &lt;ns:UnqualifiedSimpleProperty&gt;value&lt;/ns:UnqualifiedSimpleProperty&gt;
        /// &lt;ns:UnqualifiedStructProperty&gt; (If no rdf:resource qualifier)
        /// &lt;rdf:Description&gt;
        /// ... Fields, same forms as top level properties
        /// &lt;/rdf:Description&gt;
        /// &lt;/ns:UnqualifiedStructProperty&gt;
        /// &lt;ns:ResourceStructProperty rdf:resource=&quot;URI&quot;
        /// ... Fields as attributes
        /// &gt;
        /// &lt;ns:UnqualifiedArrayProperty&gt;
        /// &lt;rdf:Bag&gt; or Seq or Alt
        /// ... Array items as rdf:li elements, same forms as top level properties
        /// &lt;/rdf:Bag&gt;
        /// &lt;/ns:UnqualifiedArrayProperty&gt;
        /// &lt;ns:QualifiedProperty&gt;
        /// &lt;rdf:Description&gt;
        /// &lt;rdf:value&gt; ... Property &quot;value&quot; following the unqualified
        /// forms ... &lt;/rdf:value&gt;
        /// ... Qualifiers looking like named struct fields
        /// &lt;/rdf:Description&gt;
        /// &lt;/ns:QualifiedProperty&gt;
        /// </code>
        /// </remarks>
        /// <param name="node">the property node</param>
        /// <param name="emitAsRdfValue">property shall be rendered as attribute rather than tag</param>
        /// <param name="useCanonicalRdf">
        /// use canonical form with inner description tag or
        /// the compact form with rdf:ParseType=&quot;resource&quot; attribute.
        /// </param>
        /// <param name="indent">the current indent level</param>
        /// <exception cref="System.IO.IOException">Forwards all writer exceptions.</exception>
        /// <exception cref="XmpException">If &quot;rdf:resource&quot; and general qualifiers are mixed.</exception>
        private void SerializeCanonicalRdfProperty(XmpNode node, bool useCanonicalRdf, bool emitAsRdfValue, int indent)
        {
            var emitEndTag   = true;
            var indentEndTag = true;

            // Determine the XML element name. Open the start tag with the name and
            // attribute qualifiers.
            var elemName = node.Name;

            if (emitAsRdfValue)
            {
                elemName = "rdf:value";
            }
            else if (elemName == XmpConstants.ArrayItemName)
            {
                elemName = XmpConstants.RdfLi;
            }

            WriteIndent(indent);
            Write('<');
            Write(elemName);
            var hasGeneralQualifiers = false;
            var hasRdfResourceQual   = false;

            for (var it = node.IterateQualifier(); it.HasNext();)
            {
                var qualifier = (XmpNode)it.Next();
                if (!RdfAttrQualifier.Contains(qualifier.Name))
                {
                    hasGeneralQualifiers = true;
                }
                else
                {
                    hasRdfResourceQual = qualifier.Name == "rdf:resource";
                    if (!emitAsRdfValue)
                    {
                        Write(' ');
                        Write(qualifier.Name);
                        Write("=\"");
                        AppendNodeValue(qualifier.Value, true);
                        Write('"');
                    }
                }
            }
            // Process the property according to the standard patterns.
            if (hasGeneralQualifiers && !emitAsRdfValue)
            {
                // This node has general, non-attribute, qualifiers. Emit using the
                // qualified property form.
                // ! The value is output by a recursive call ON THE SAME NODE with
                // emitAsRDFValue set.
                if (hasRdfResourceQual)
                {
                    throw new XmpException("Can't mix rdf:resource and general qualifiers", XmpErrorCode.BadRdf);
                }

                // Change serialization to canonical format with inner rdf:Description-tag
                // depending on option
                if (useCanonicalRdf)
                {
                    Write(">");
                    WriteNewline();
                    indent++;
                    WriteIndent(indent);
                    Write(RdfStructStart);
                    Write(">");
                }
                else
                {
                    Write(" rdf:parseType=\"Resource\">");
                }

                WriteNewline();
                SerializeCanonicalRdfProperty(node, useCanonicalRdf, true, indent + 1);

                for (var it = node.IterateQualifier(); it.HasNext();)
                {
                    var qualifier = (XmpNode)it.Next();
                    if (!RdfAttrQualifier.Contains(qualifier.Name))
                    {
                        SerializeCanonicalRdfProperty(qualifier, useCanonicalRdf, false, indent + 1);
                    }
                }

                if (useCanonicalRdf)
                {
                    WriteIndent(indent);
                    Write(RdfStructEnd);
                    WriteNewline();
                    indent--;
                }
            }
            else
            {
                // This node has no general qualifiers. Emit using an unqualified form.
                if (!node.Options.IsCompositeProperty)
                {
                    // This is a simple property.
                    if (node.Options.IsUri)
                    {
                        Write(" rdf:resource=\"");
                        AppendNodeValue(node.Value, true);
                        Write("\"/>");
                        WriteNewline();
                        emitEndTag = false;
                    }
                    else if (string.IsNullOrEmpty(node.Value))
                    {
                        Write("/>");
                        WriteNewline();
                        emitEndTag = false;
                    }
                    else
                    {
                        Write('>');
                        AppendNodeValue(node.Value, false);
                        indentEndTag = false;
                    }
                }
                else
                {
                    if (node.Options.IsArray)
                    {
                        // This is an array.
                        Write('>');
                        WriteNewline();
                        EmitRdfArrayTag(node, true, indent + 1);

                        if (node.Options.IsArrayAltText)
                        {
                            XmpNodeUtils.NormalizeLangArray(node);
                        }

                        for (var it1 = node.IterateChildren(); it1.HasNext();)
                        {
                            var child = (XmpNode)it1.Next();
                            SerializeCanonicalRdfProperty(child, useCanonicalRdf, false, indent + 2);
                        }

                        EmitRdfArrayTag(node, false, indent + 1);
                    }
                    else if (!hasRdfResourceQual)
                    {
                        // This is a "normal" struct, use the rdf:parseType="Resource" form.
                        if (!node.HasChildren)
                        {
                            // Change serialization to canonical format with inner rdf:Description-tag
                            // if option is set
                            if (useCanonicalRdf)
                            {
                                Write(">");
                                WriteNewline();
                                WriteIndent(indent + 1);
                                Write(RdfEmptyStruct);
                            }
                            else
                            {
                                Write(" rdf:parseType=\"Resource\"/>");
                                emitEndTag = false;
                            }

                            WriteNewline();
                        }
                        else
                        {
                            // Change serialization to canonical format with inner rdf:Description-tag
                            // if option is set
                            if (useCanonicalRdf)
                            {
                                Write(">");
                                WriteNewline();
                                indent++;
                                WriteIndent(indent);
                                Write(RdfStructStart);
                                Write(">");
                            }
                            else
                            {
                                Write(" rdf:parseType=\"Resource\">");
                            }

                            WriteNewline();
                            for (var it = node.IterateChildren(); it.HasNext();)
                            {
                                var child = (XmpNode)it.Next();
                                SerializeCanonicalRdfProperty(child, useCanonicalRdf, false, indent + 1);
                            }

                            if (useCanonicalRdf)
                            {
                                WriteIndent(indent);
                                Write(RdfStructEnd);
                                WriteNewline();
                                indent--;
                            }
                        }
                    }
                    else
                    {
                        // This is a struct with an rdf:resource attribute, use the
                        // "empty property element" form.
                        for (var it1 = node.IterateChildren(); it1.HasNext();)
                        {
                            var child = (XmpNode)it1.Next();
                            if (!CanBeRdfAttrProp(child))
                            {
                                throw new XmpException("Can't mix rdf:resource and complex fields", XmpErrorCode.BadRdf);
                            }

                            WriteNewline();
                            WriteIndent(indent + 1);
                            Write(' ');
                            Write(child.Name);
                            Write("=\"");
                            AppendNodeValue(child.Value, true);
                            Write('"');
                        }

                        Write("/>");
                        WriteNewline();
                        emitEndTag = false;
                    }
                }
            }
            // Emit the property element end tag.
            if (emitEndTag)
            {
                if (indentEndTag)
                {
                    WriteIndent(indent);
                }
                Write("</");
                Write(elemName);
                Write('>');
                WriteNewline();
            }
        }