// EMPTY /// <summary> /// Parses the input source into an XMP metadata object, including /// de-aliasing and normalisation. /// </summary> /// <param name="input"> /// the input can be an <code>InputStream</code>, a <code>String</code> or /// a byte buffer containing the XMP packet. /// </param> /// <param name="options">the parse options</param> /// <returns>Returns the resulting XMP metadata object</returns> /// <exception cref="Com.Adobe.Xmp.XMPException">Thrown if parsing or normalisation fails.</exception> public static XMPMeta Parse(object input, ParseOptions options) { ParameterAsserts.AssertNotNull(input); options = options != null ? options : new ParseOptions(); XmlDocument document = ParseXml(input, options); bool xmpmetaRequired = options.GetRequireXMPMeta(); object[] result = new object[3]; result = FindRootNode(document, xmpmetaRequired, result); if (result != null && result[1] == XmpRdf) { XMPMetaImpl xmp = ParseRDF.Parse((XmlNode)result[0]); xmp.SetPacketHeader((string)result[2]); // Check if the XMP object shall be normalized if (!options.GetOmitNormalization()) { return XMPNormalizer.Process(xmp, options); } else { return xmp; } } else { // no appropriate root node found, return empty metadata object return new XMPMetaImpl(); } }
// EMPTY /// <summary>Normalizes a raw parsed XMPMeta-Object</summary> /// <param name="xmp">the raw metadata object</param> /// <param name="options">the parsing options</param> /// <returns>Returns the normalized metadata object</returns> /// <exception cref="Com.Adobe.Xmp.XMPException">Collects all severe processing errors.</exception> internal static XMPMeta Process(XMPMetaImpl xmp, ParseOptions options) { XMPNode tree = xmp.GetRoot(); TouchUpDataModel(xmp); MoveExplicitAliases(tree, options); TweakOldXMP(tree); DeleteEmptySchemas(tree); return xmp; }
/// <seealso cref="Com.Adobe.Xmp.XMPMeta.Normalize(Com.Adobe.Xmp.Options.ParseOptions)"/> /// <exception cref="Com.Adobe.Xmp.XMPException"/> public virtual void Normalize(ParseOptions options) { if (options == null) { options = new ParseOptions(); } XMPNormalizer.Process(this, options); }
/// <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); } }
/// <summary>Parses the raw XML metadata packet considering the parsing options.</summary> /// <remarks> /// Parses the raw XML metadata packet considering the parsing options. /// Latin-1/ISO-8859-1 can be accepted when the input is a byte stream /// (some old toolkits versions such packets). The stream is /// then wrapped in another stream that converts Latin-1 to UTF-8. /// <p> /// If control characters shall be fixed, a reader is used that fixes the chars to spaces /// (if the input is a byte stream is has to be read as character stream). /// <p> /// Both options reduce the performance of the parser. /// </remarks> /// <param name="input"> /// the input can be an <code>InputStream</code>, a <code>String</code> or /// a byte buffer containing the XMP packet. /// </param> /// <param name="options">the parsing options</param> /// <returns>Returns the parsed XML document or an exception.</returns> /// <exception cref="Com.Adobe.Xmp.XMPException">Thrown if the parsing fails for different reasons</exception> private static XmlDocument ParseXml(object input, ParseOptions options) { if (input is InputStream) { return ParseXmlFromInputStream((InputStream)input, options); } else { if (input is sbyte[]) { return ParseXmlFromBytebuffer(new ByteBuffer((sbyte[])input), options); } else { return ParseXmlFromString((string)input, options); } } }
/// <summary> /// Parses XML from a /// <see cref="string"/> /// , /// fixing the illegal control character optionally. /// </summary> /// <param name="input">a <code>String</code> containing the XMP packet</param> /// <param name="options">the parsing options</param> /// <returns>Returns an XML DOM-Document.</returns> /// <exception cref="Com.Adobe.Xmp.XMPException">Thrown when the parsing fails.</exception> private static XmlDocument ParseXmlFromString(string input, ParseOptions options) { InputSource source = new InputSource(new Sharpen.StringReader(input)); try { return ParseInputSource(source); } catch (XMPException e) { if (e.GetErrorCode() == XMPErrorConstants.Badxml && options.GetFixControlChars()) { source = new InputSource(new FixASCIIControlsReader(new Sharpen.StringReader(input))); return ParseInputSource(source); } else { throw; } } }
/// <summary> /// Parses XML from a byte buffer, /// fixing the encoding (Latin-1 to UTF-8) and illegal control character optionally. /// </summary> /// <param name="buffer">a byte buffer containing the XMP packet</param> /// <param name="options">the parsing options</param> /// <returns>Returns an XML DOM-Document.</returns> /// <exception cref="Com.Adobe.Xmp.XMPException">Thrown when the parsing fails.</exception> private static XmlDocument ParseXmlFromBytebuffer(ByteBuffer buffer, ParseOptions options) { InputSource source = new InputSource(buffer.GetByteStream()); try { return ParseInputSource(source); } catch (XMPException e) { if (e.GetErrorCode() == XMPErrorConstants.Badxml || e.GetErrorCode() == XMPErrorConstants.Badstream) { if (options.GetAcceptLatin1()) { buffer = Latin1Converter.Convert(buffer); } if (options.GetFixControlChars()) { try { string encoding = buffer.GetEncoding(); System.IO.StreamReader fixReader = new FixASCIIControlsReader(new InputStreamReader(buffer.GetByteStream(), encoding)); return ParseInputSource(new InputSource(fixReader)); } catch (UnsupportedEncodingException) { // can normally not happen as the encoding is provided by a util function throw new XMPException("Unsupported Encoding", XMPErrorConstants.Internalfailure, e); } } source = new InputSource(buffer.GetByteStream()); return ParseInputSource(source); } else { throw; } } }
/// <summary> /// Parses XML from an /// <see cref="InputStream"/> /// , /// fixing the encoding (Latin-1 to UTF-8) and illegal control character optionally. /// </summary> /// <param name="stream">an <code>InputStream</code></param> /// <param name="options">the parsing options</param> /// <returns>Returns an XML DOM-Document.</returns> /// <exception cref="Com.Adobe.Xmp.XMPException">Thrown when the parsing fails.</exception> private static XmlDocument ParseXmlFromInputStream(InputStream stream, ParseOptions options) { if (!options.GetAcceptLatin1() && !options.GetFixControlChars()) { return ParseInputSource(new InputSource(stream)); } else { // load stream into bytebuffer try { ByteBuffer buffer = new ByteBuffer(stream); return ParseXmlFromBytebuffer(buffer, options); } catch (IOException e) { throw new XMPException("Error reading the XML-file", XMPErrorConstants.Badstream, e); } } }
/// <summary>Creates an <code>XMPMeta</code>-object from a string.</summary> /// <seealso cref="ParseFromString(string, Com.Adobe.Xmp.Options.ParseOptions)"/> /// <param name="packet">a String contain an XMP-file.</param> /// <param name="options">Options controlling the parsing.</param> /// <returns>Returns the <code>XMPMeta</code>-object created from the input.</returns> /// <exception cref="XMPException">If the file is not well-formed XML or if the parsing fails.</exception> /// <exception cref="Com.Adobe.Xmp.XMPException"/> public static XMPMeta ParseFromString(string packet, ParseOptions options) { return XMPMetaParser.Parse(packet, options); }
/// <summary>Creates an <code>XMPMeta</code>-object from a byte-buffer.</summary> /// <seealso cref="Parse(System.IO.InputStream, Com.Adobe.Xmp.Options.ParseOptions)"/> /// <param name="buffer">a String contain an XMP-file.</param> /// <param name="options">Options controlling the parsing.</param> /// <returns>Returns the <code>XMPMeta</code>-object created from the input.</returns> /// <exception cref="XMPException">If the file is not well-formed XML or if the parsing fails.</exception> /// <exception cref="Com.Adobe.Xmp.XMPException"/> public static XMPMeta ParseFromBuffer(sbyte[] buffer, ParseOptions options) { return XMPMetaParser.Parse(buffer, options); }
/// <summary> /// These functions support parsing serialized RDF into an XMP object, and serailizing an XMP /// object into RDF. /// </summary> /// <remarks> /// These functions support parsing serialized RDF into an XMP object, and serailizing an XMP /// object into RDF. The input for parsing may be any valid Unicode /// encoding. ISO Latin-1 is also recognized, but its use is strongly discouraged. Serialization /// is always as UTF-8. /// <p> /// <code>parseFromBuffer()</code> parses RDF from an <code>InputStream</code>. The encoding /// is recognized automatically. /// </remarks> /// <param name="in">an <code>InputStream</code></param> /// <param name="options"> /// Options controlling the parsing.<br /> /// The available options are: /// <ul> /// <li> XMP_REQUIRE_XMPMETA - The <x:xmpmeta> XML element is required around /// <tt><rdf:RDF></tt>. /// <li> XMP_STRICT_ALIASING - Do not reconcile alias differences, throw an exception. /// </ul> /// <em>Note:</em>The XMP_STRICT_ALIASING option is not yet implemented. /// </param> /// <returns>Returns the <code>XMPMeta</code>-object created from the input.</returns> /// <exception cref="XMPException">If the file is not well-formed XML or if the parsing fails.</exception> /// <exception cref="Com.Adobe.Xmp.XMPException"/> public static XMPMeta Parse(InputStream @in, ParseOptions options) { return XMPMetaParser.Parse(@in, options); }