Beispiel #1
0
        /// <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="iText.Kernel.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", XMPError.BADXPATH);
            }
            String       rootProp  = VerifyXPathRoot(schemaNS, pos.path.JSubstring(pos.stepBegin, pos.stepEnd));
            XMPAliasInfo aliasInfo = XMPMetaFactory.GetSchemaRegistry().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.GetNamespace(), XMPPath.SCHEMA_NODE));
                XMPPathSegment rootStep = new XMPPathSegment(VerifyXPathRoot(aliasInfo.GetNamespace(), aliasInfo.GetPropName
                                                                                 ()), XMPPath.STRUCT_FIELD_STEP);
                rootStep.SetAlias(true);
                rootStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
                expandedXPath.Add(rootStep);
                if (aliasInfo.GetAliasForm().IsArrayAltText())
                {
                    XMPPathSegment qualSelectorStep = new XMPPathSegment("[?xml:lang='x-default']", XMPPath.QUAL_SELECTOR_STEP
                                                                         );
                    qualSelectorStep.SetAlias(true);
                    qualSelectorStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
                    expandedXPath.Add(qualSelectorStep);
                }
                else
                {
                    if (aliasInfo.GetAliasForm().IsArray())
                    {
                        XMPPathSegment indexStep = new XMPPathSegment("[1]", XMPPath.ARRAY_INDEX_STEP);
                        indexStep.SetAlias(true);
                        indexStep.SetAliasForm(aliasInfo.GetAliasForm().GetOptions());
                        expandedXPath.Add(indexStep);
                    }
                }
            }
        }
Beispiel #2
0
        // empty
        /// <summary>
        /// Split an XMPPath expression apart at the conceptual steps, adding the
        /// root namespace prefix to the first property component.
        /// </summary>
        /// <remarks>
        /// 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.
        /// <para />
        /// 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>
        /// <para />
        /// 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]".
        /// <para />
        /// 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.
        /// <para />
        /// 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.
        /// </remarks>
        /// <param name="schemaNS">schema namespace</param>
        /// <param name="path">property name</param>
        /// <returns>Returns the expandet XMPPath.</returns>
        /// <exception cref="iText.Kernel.XMP.XMPException">Thrown if the format is not correct somehow.</exception>
        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;
                if (path[pos.stepBegin] != '[')
                {
                    // A struct field or qualifier.
                    segment = ParseStructSegment(pos);
                }
                else
                {
                    // One of the array forms.
                    segment = ParseIndexSegment(pos);
                }
                if (segment.GetKind() == XMPPath.STRUCT_FIELD_STEP)
                {
                    if (segment.GetName()[0] == '@')
                    {
                        segment.SetName("?" + segment.GetName().Substring(1));
                        if (!"?xml:lang".Equals(segment.GetName()))
                        {
                            throw new XMPException("Only xml:lang allowed with '@'", XMPError.BADXPATH);
                        }
                    }
                    if (segment.GetName()[0] == '?')
                    {
                        pos.nameStart++;
                        segment.SetKind(XMPPath.QUALIFIER_STEP);
                    }
                    VerifyQualName(pos.path.JSubstring(pos.nameStart, pos.nameEnd));
                }
                else
                {
                    if (segment.GetKind() == XMPPath.FIELD_SELECTOR_STEP)
                    {
                        if (segment.GetName()[1] == '@')
                        {
                            segment.SetName("[?" + segment.GetName().Substring(2));
                            if (!segment.GetName().StartsWith("[?xml:lang="))
                            {
                                throw new XMPException("Only xml:lang allowed with '@'", XMPError.BADXPATH);
                            }
                        }
                        if (segment.GetName()[1] == '?')
                        {
                            pos.nameStart++;
                            segment.SetKind(XMPPath.QUAL_SELECTOR_STEP);
                            VerifyQualName(pos.path.JSubstring(pos.nameStart, pos.nameEnd));
                        }
                    }
                }
                expandedXPath.Add(segment);
            }
            return(expandedXPath);
        }