/// <summary>Find or create a schema node if <code>createNodes</code> is true.</summary> /// <param name="tree">the root of the xmp tree.</param> /// <param name="namespaceURI">a namespace</param> /// <param name="suggestedPrefix">If a prefix is suggested, the namespace is allowed to be registered.</param> /// <param name="createNodes"> /// a flag indicating if the node shall be created if not found. /// <em>Note:</em> The namespace must be registered prior to this call. /// </param> /// <returns> /// Returns the schema node if found, <code>null</code> otherwise. /// Note: If <code>createNodes</code> is <code>true</code>, it is <b>always</b> /// returned a valid node. /// </returns> /// <exception cref="Com.Adobe.Xmp.XMPException"> /// An exception is only thrown if an error occurred, not if a /// node was not found. /// </exception> internal static XMPNode FindSchemaNode(XMPNode tree, string namespaceURI, string suggestedPrefix, bool createNodes) { System.Diagnostics.Debug.Assert(tree.GetParent() == null); // make sure that its the root XMPNode schemaNode = tree.FindChildByName(namespaceURI); if (schemaNode == null && createNodes) { schemaNode = new XMPNode(namespaceURI, new PropertyOptions().SetSchemaNode(true)); schemaNode.SetImplicit(true); // only previously registered schema namespaces are allowed in the XMP tree. string prefix = XMPMetaFactory.GetSchemaRegistry().GetNamespacePrefix(namespaceURI); if (prefix == null) { if (suggestedPrefix != null && suggestedPrefix.Length != 0) { prefix = XMPMetaFactory.GetSchemaRegistry().RegisterNamespace(namespaceURI, suggestedPrefix); } else { throw new XMPException("Unregistered schema namespace URI", XMPErrorConstants.Badschema); } } schemaNode.SetValue(prefix); tree.AddChild(schemaNode); } return(schemaNode); }
public virtual string GetNamespace() { if (!node.GetOptions().IsSchemaNode()) { // determine namespace of leaf node QName qname = new QName(node.GetName()); return(XMPMetaFactory.GetSchemaRegistry().GetNamespaceURI(qname.GetPrefix())); } return(baseNs); }
/// <summary>Set up the first 2 components of the expanded XMPPath.</summary> /// <remarks> /// Set up the first 2 components of the expanded XMPPath. Normalizes the various cases of using /// the full schema URI and/or a qualified root property name. Returns true for normal /// processing. If allowUnknownSchemaNS is true and the schema namespace is not registered, false /// is returned. If allowUnknownSchemaNS is false and the schema namespace is not registered, an /// exception is thrown /// <P> /// (Should someday check the full syntax:) /// </remarks> /// <param name="schemaNS">schema namespace</param> /// <param name="rootProp">the root xpath segment</param> /// <returns>Returns root QName.</returns> /// <exception cref="Com.Adobe.Xmp.XMPException">Thrown if the format is not correct somehow.</exception> private static string VerifyXPathRoot(string schemaNS, string rootProp) { // Do some basic checks on the URI and name. Try to lookup the URI. See if the name is // qualified. if (schemaNS == null || schemaNS.Length == 0) { throw new XMPException("Schema namespace URI is required", XMPErrorConstants.Badschema); } if ((rootProp[0] == '?') || (rootProp[0] == '@')) { throw new XMPException("Top level name must not be a qualifier", XMPErrorConstants.Badxpath); } if (rootProp.IndexOf('/') >= 0 || rootProp.IndexOf('[') >= 0) { throw new XMPException("Top level name must be simple", XMPErrorConstants.Badxpath); } string prefix = XMPMetaFactory.GetSchemaRegistry().GetNamespacePrefix(schemaNS); if (prefix == null) { throw new XMPException("Unregistered schema namespace URI", XMPErrorConstants.Badschema); } // Verify the various URI and prefix combinations. Initialize the // expanded XMPPath. int colonPos = rootProp.IndexOf(':'); if (colonPos < 0) { // The propName is unqualified, use the schemaURI and associated // prefix. VerifySimpleXMLName(rootProp); // Verify the part before any colon return(prefix + rootProp); } else { // The propName is qualified. Make sure the prefix is legit. Use the associated URI and // qualified name. // Verify the part before any colon VerifySimpleXMLName(Sharpen.Runtime.Substring(rootProp, 0, colonPos)); VerifySimpleXMLName(Sharpen.Runtime.Substring(rootProp, colonPos)); prefix = Sharpen.Runtime.Substring(rootProp, 0, colonPos + 1); string regPrefix = XMPMetaFactory.GetSchemaRegistry().GetNamespacePrefix(schemaNS); if (regPrefix == null) { throw new XMPException("Unknown schema namespace prefix", XMPErrorConstants.Badschema); } if (!prefix.Equals(regPrefix)) { throw new XMPException("Schema namespace URI and prefix mismatch", XMPErrorConstants.Badschema); } return(rootProp); } }
/// <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 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> /// Verifies whether the qualifier name is not XML conformant or the /// namespace prefix has not been registered. /// </summary> /// <param name="qualName">a qualifier name</param> /// <exception cref="Com.Adobe.Xmp.XMPException">If the name is not conformant</exception> private static void VerifyQualName(string qualName) { int colonPos = qualName.IndexOf(':'); if (colonPos > 0) { string prefix = Sharpen.Runtime.Substring(qualName, 0, colonPos); if (Utils.IsXMLNameNS(prefix)) { string regURI = XMPMetaFactory.GetSchemaRegistry().GetNamespaceURI(prefix); if (regURI != null) { return; } throw new XMPException("Unknown namespace prefix for qualified name", XMPErrorConstants.Badxpath); } } throw new XMPException("Ill-formed qualified name", XMPErrorConstants.Badxpath); }
/// <summary> /// Verifies whether the qualifier name is not XML conformant or the /// namespace prefix has not been registered. /// </summary> /// <param name="qualName">a qualifier name</param> /// <exception cref="iText.Kernel.XMP.XMPException">If the name is not conformant</exception> private static void VerifyQualName(String qualName) { int colonPos = qualName.IndexOf(':'); if (colonPos > 0) { String prefix = qualName.JSubstring(0, colonPos); if (Utils.IsXMLNameNS(prefix)) { String regURI = XMPMetaFactory.GetSchemaRegistry().GetNamespaceURI(prefix); if (regURI != null) { return; } throw new XMPException("Unknown namespace prefix for qualified name", XMPError.BADXPATH); } } throw new XMPException("Ill-formed qualified name", XMPError.BADXPATH); }
/// <summary>Visit all of the top level nodes looking for aliases.</summary> /// <remarks> /// Visit all of the top level nodes looking for aliases. If there is /// no base, transplant the alias subtree. If there is a base and strict /// aliasing is on, make sure the alias and base subtrees match. /// </remarks> /// <param name="tree">the root of the metadata tree</param> /// <param name="options">th parsing options</param> /// <exception cref="Com.Adobe.Xmp.XMPException">Forwards XMP errors</exception> private static void MoveExplicitAliases(XMPNode tree, ParseOptions options) { if (!tree.GetHasAliases()) { return; } tree.SetHasAliases(false); bool strictAliasing = options.GetStrictAliasing(); for (Iterator schemaIt = tree.GetUnmodifiableChildren().Iterator(); schemaIt.HasNext();) { XMPNode currSchema = (XMPNode)schemaIt.Next(); if (!currSchema.GetHasAliases()) { continue; } for (Iterator propertyIt = currSchema.IterateChildren(); propertyIt.HasNext();) { XMPNode currProp = (XMPNode)propertyIt.Next(); if (!currProp.IsAlias()) { continue; } currProp.SetAlias(false); // Find the base path, look for the base schema and root node. XMPAliasInfo info = XMPMetaFactory.GetSchemaRegistry().FindAlias(currProp.GetName()); if (info != null) { // find or create schema XMPNode baseSchema = XMPNodeUtils.FindSchemaNode(tree, info.GetNamespace(), null, true); baseSchema.SetImplicit(false); XMPNode baseNode = XMPNodeUtils.FindChildNode(baseSchema, info.GetPrefix() + info.GetPropName(), false); if (baseNode == null) { if (info.GetAliasForm().IsSimple()) { // A top-to-top alias, transplant the property. // change the alias property name to the base name string qname = info.GetPrefix() + info.GetPropName(); currProp.SetName(qname); baseSchema.AddChild(currProp); // remove the alias property propertyIt.Remove(); } else { // An alias to an array item, // create the array and transplant the property. baseNode = new XMPNode(info.GetPrefix() + info.GetPropName(), info.GetAliasForm().ToPropertyOptions()); baseSchema.AddChild(baseNode); TransplantArrayItemAlias(propertyIt, currProp, baseNode); } } else { if (info.GetAliasForm().IsSimple()) { // The base node does exist and this is a top-to-top alias. // Check for conflicts if strict aliasing is on. // Remove and delete the alias subtree. if (strictAliasing) { CompareAliasedSubtrees(currProp, baseNode, true); } propertyIt.Remove(); } else { // This is an alias to an array item and the array exists. // Look for the aliased item. // Then transplant or check & delete as appropriate. XMPNode itemNode = null; if (info.GetAliasForm().IsArrayAltText()) { int xdIndex = XMPNodeUtils.LookupLanguageItem(baseNode, XMPConstConstants.XDefault); if (xdIndex != -1) { itemNode = baseNode.GetChild(xdIndex); } } else { if (baseNode.HasChildren()) { itemNode = baseNode.GetChild(1); } } if (itemNode == null) { TransplantArrayItemAlias(propertyIt, currProp, baseNode); } else { if (strictAliasing) { CompareAliasedSubtrees(currProp, itemNode, true); } propertyIt.Remove(); } } } } } currSchema.SetHasAliases(false); } }
/// <seealso cref="Com.Adobe.Xmp.XMPUtils.RemoveProperties(Com.Adobe.Xmp.XMPMeta, string, string, bool, bool)"/> /// <param name="xmp">The XMP object containing the properties to be removed.</param> /// <param name="schemaNS"> /// Optional schema namespace URI for the properties to be /// removed. /// </param> /// <param name="propName">Optional path expression for the property to be removed.</param> /// <param name="doAllProperties"> /// Option flag to control the deletion: do internal properties in /// addition to external properties. /// </param> /// <param name="includeAliases"> /// Option flag to control the deletion: Include aliases in the /// "named schema" case above. /// </param> /// <exception cref="Com.Adobe.Xmp.XMPException">If metadata processing fails</exception> public static void RemoveProperties(XMPMeta xmp, string schemaNS, string propName, bool doAllProperties, bool includeAliases) { ParameterAsserts.AssertImplementation(xmp); XMPMetaImpl xmpImpl = (XMPMetaImpl)xmp; if (propName != null && propName.Length > 0) { // Remove just the one indicated property. This might be an alias, // the named schema might not actually exist. So don't lookup the // schema node. if (schemaNS == null || schemaNS.Length == 0) { throw new XMPException("Property name requires schema namespace", XMPErrorConstants.Badparam); } XMPPath expPath = XMPPathParser.ExpandXPath(schemaNS, propName); XMPNode propNode = XMPNodeUtils.FindNode(xmpImpl.GetRoot(), expPath, false, null); if (propNode != null) { if (doAllProperties || !Utils.IsInternalProperty(expPath.GetSegment(XMPPath.StepSchema).GetName(), expPath.GetSegment(XMPPath.StepRootProp).GetName())) { XMPNode parent = propNode.GetParent(); parent.RemoveChild(propNode); if (parent.GetOptions().IsSchemaNode() && !parent.HasChildren()) { // remove empty schema node parent.GetParent().RemoveChild(parent); } } } } else { if (schemaNS != null && schemaNS.Length > 0) { // Remove all properties from the named schema. Optionally include // aliases, in which case // there might not be an actual schema node. // XMP_NodePtrPos schemaPos; XMPNode schemaNode = XMPNodeUtils.FindSchemaNode(xmpImpl.GetRoot(), schemaNS, false); if (schemaNode != null) { if (RemoveSchemaChildren(schemaNode, doAllProperties)) { xmpImpl.GetRoot().RemoveChild(schemaNode); } } if (includeAliases) { // We're removing the aliases also. Look them up by their // namespace prefix. // But that takes more code and the extra speed isn't worth it. // Lookup the XMP node // from the alias, to make sure the actual exists. XMPAliasInfo[] aliases = XMPMetaFactory.GetSchemaRegistry().FindAliases(schemaNS); for (int i = 0; i < aliases.Length; i++) { XMPAliasInfo info = aliases[i]; XMPPath path = XMPPathParser.ExpandXPath(info.GetNamespace(), info.GetPropName()); XMPNode actualProp = XMPNodeUtils.FindNode(xmpImpl.GetRoot(), path, false, null); if (actualProp != null) { XMPNode parent = actualProp.GetParent(); parent.RemoveChild(actualProp); } } } } else { // Remove all appropriate properties from all schema. In this case // we don't have to be // concerned with aliases, they are handled implicitly from the // actual properties. for (Iterator it = xmpImpl.GetRoot().IterateChildren(); it.HasNext();) { XMPNode schema = (XMPNode)it.Next(); if (RemoveSchemaChildren(schema, doAllProperties)) { it.Remove(); } } } } }