/// <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); } } } }
/// <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="iText.Kernel.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", XMPError.BADXPATH); } // ! Touch up later, also changing '@' to '?'. XMPPathSegment segment = new XMPPathSegment(pos.path.JSubstring(pos.stepBegin, pos.stepEnd), XMPPath.STRUCT_FIELD_STEP ); return(segment); }
/// <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 an array index segment.</summary> /// <param name="pos">the xmp path</param> /// <returns>Returns the segment or an error</returns> /// <exception cref="iText.Kernel.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.ARRAY_INDEX_STEP); } 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", XMPError.BADXPATH); } if (pos.path[pos.stepEnd] == ']') { if (!"[last()".Equals(pos.path.JSubstring(pos.stepBegin, pos.stepEnd))) { throw new XMPException("Invalid non-numeric array index", XMPError.BADXPATH); } segment = new XMPPathSegment(null, XMPPath.ARRAY_LAST_STEP); } 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", XMPError.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", XMPError.BADXPATH); } pos.stepEnd++; // Absorb the trailing quote. // ! Touch up later, also changing '@' to '?'. segment = new XMPPathSegment(null, XMPPath.FIELD_SELECTOR_STEP); } } if (pos.stepEnd >= pos.path.Length || pos.path[pos.stepEnd] != ']') { throw new XMPException("Missing ']' for array index", XMPError.BADXPATH); } pos.stepEnd++; segment.SetName(pos.path.JSubstring(pos.stepBegin, pos.stepEnd)); return(segment); }