/// <summary>Find or create a qualifier node under a given parent node.</summary> /// <remarks> /// Find or create a qualifier node under a given parent node. Returns a pointer to the /// qualifier node, and optionally an iterator for the node's position in /// the parent's vector of qualifiers. The iterator is unchanged if no qualifier node (null) /// is returned. /// <em>Note:</em> On entry, the qualName parameter must not have the leading '?' from the /// XMPPath step. /// </remarks> /// <param name="parent">the parent XMPNode</param> /// <param name="qualName">the qualifier name</param> /// <param name="createNodes">flag if nodes shall be created</param> /// <returns>Returns the qualifier node if found or created, <code>null</code> otherwise. /// </returns> /// <exception cref="iText.Kernel.XMP.XMPException"></exception> private static XMPNode FindQualifierNode(XMPNode parent, String qualName, bool createNodes ) { System.Diagnostics.Debug.Assert(!qualName.StartsWith("?")); XMPNode qualNode = parent.FindQualifierByName(qualName); if (qualNode == null && createNodes) { qualNode = new XMPNode(qualName, null); qualNode.SetImplicit(true); parent.AddQualifier(qualNode); } return(qualNode); }
/// <summary>Make sure that the array is well-formed AltText.</summary> /// <remarks> /// Make sure that the array is well-formed AltText. Each item must be simple /// and have an "xml:lang" qualifier. If repairs are needed, keep simple /// non-empty items by adding the "xml:lang" with value "x-repair". /// </remarks> /// <param name="arrayNode">the property node of the array to repair.</param> /// <exception cref="iText.Kernel.XMP.XMPException">Forwards unexpected exceptions. /// </exception> private static void RepairAltText(XMPNode arrayNode) { if (arrayNode == null || !arrayNode.GetOptions().IsArray()) { // Already OK or not even an array. return; } // fix options arrayNode.GetOptions().SetArrayOrdered(true); arrayNode.GetOptions().SetArrayAlternate(true); arrayNode.GetOptions().SetArrayAltText(true); ArrayList currChildsToRemove = new ArrayList(); IEnumerator it = arrayNode.IterateChildren(); while (it.MoveNext()) { XMPNode currChild = (XMPNode)it.Current; if (currChild == null) { continue; } if (currChild.GetOptions().IsCompositeProperty()) { // Delete non-simple children. currChildsToRemove.Add(currChild); } else if (!currChild.GetOptions().GetHasLanguage()) { string childValue = currChild.GetValue(); if (String.IsNullOrEmpty(childValue)) { // Delete empty valued children that have no xml:lang. currChildsToRemove.Add(currChild); } else { // Add an xml:lang qualifier with the value "x-repair". XMPNode repairLang = new XMPNode(XMPConst.XML_LANG, "x-repair", null); currChild.AddQualifier(repairLang); } } } foreach (object o in currChildsToRemove) { arrayNode.GetChildren().Remove(o); } }
/// <summary>Appends a language item to an alt text array.</summary> /// <param name="arrayNode">the language array</param> /// <param name="itemLang">the language of the item</param> /// <param name="itemValue">the content of the item</param> /// <exception cref="iText.Kernel.XMP.XMPException">Thrown if a duplicate property is added /// </exception> internal static void AppendLangItem(XMPNode arrayNode, String itemLang, String itemValue ) { XMPNode newItem = new XMPNode(ARRAY_ITEM_NAME, itemValue, null); XMPNode langQual = new XMPNode(XML_LANG, itemLang, null); newItem.AddQualifier(langQual); if (!X_DEFAULT.Equals(langQual.GetValue())) { arrayNode.AddChild(newItem); } else { arrayNode.AddChild(1, newItem); } }
/// <summary> /// Moves an alias node of array form to another schema into an array </summary> /// <param name="childNode"> the node to be moved </param> /// <param name="baseArray"> the base array for the array item </param> /// <exception cref="XMPException"> Forwards XMP errors </exception> private static void TransplantArrayItemAlias(XMPNode childNode, XMPNode baseArray) { if (baseArray.GetOptions().IsArrayAltText()) { if (childNode.GetOptions().GetHasLanguage()) { throw new XMPException("Alias to x-default already has a language qualifier", XMPError.BADXMP); } XMPNode langQual = new XMPNode(XMPConst.XML_LANG, XMPConst.X_DEFAULT, null); childNode.AddQualifier(langQual); } childNode.SetName(XMPConst.ARRAY_ITEM_NAME); baseArray.AddChild(childNode); }
/// <summary> /// Undo the denormalization performed by the XMP used in Acrobat 5.<br /> /// If a Dublin Core array had only one item, it was serialized as a simple /// property. /// </summary> /// <remarks> /// Undo the denormalization performed by the XMP used in Acrobat 5.<br /> /// If a Dublin Core array had only one item, it was serialized as a simple /// property. <br /> /// The <code>xml:lang</code> attribute was dropped from an /// <code>alt-text</code> item if the language was <code>x-default</code>. /// </remarks> /// <param name="dcSchema">the DC schema node</param> /// <exception cref="iText.Kernel.XMP.XMPException">Thrown if normalization fails /// </exception> private static void NormalizeDCArrays(XMPNode dcSchema) { for (int i = 1; i <= dcSchema.GetChildrenLength(); i++) { XMPNode currProp = dcSchema.GetChild(i); PropertyOptions arrayForm = (PropertyOptions)dcArrayForms[currProp.GetName()]; if (arrayForm == null) { continue; } else { if (currProp.GetOptions().IsSimple()) { // create a new array and add the current property as child, // if it was formerly simple XMPNode newArray = new XMPNode(currProp.GetName(), arrayForm); currProp.SetName(XMPConst.ARRAY_ITEM_NAME); newArray.AddChild(currProp); dcSchema.ReplaceChild(i, newArray); // fix language alternatives if (arrayForm.IsArrayAltText() && !currProp.GetOptions().GetHasLanguage()) { XMPNode newLang = new XMPNode(XMPConst.XML_LANG, XMPConst.X_DEFAULT, null); currProp.AddQualifier(newLang); } } else { // clear array options and add corrected array form if it has been an array before currProp.GetOptions().SetOption(PropertyOptions.ARRAY | PropertyOptions.ARRAY_ORDERED | PropertyOptions.ARRAY_ALTERNATE | PropertyOptions.ARRAY_ALT_TEXT, false); currProp.GetOptions().MergeWith(arrayForm); if (arrayForm.IsArrayAltText()) { // applying for "dc:description", "dc:rights", "dc:title" RepairAltText(currProp); } } } } }
/// <summary> /// Searches for a qualifier selector in a node: /// [?qualName="value"] - an element in an array, chosen by a qualifier value. /// </summary> /// <remarks> /// Searches for a qualifier selector in a node: /// [?qualName="value"] - an element in an array, chosen by a qualifier value. /// No implicit nodes are created for qualifier selectors, /// except for an alias to an x-default item. /// </remarks> /// <param name="arrayNode">an array node</param> /// <param name="qualName">the qualifier name</param> /// <param name="qualValue">the qualifier value</param> /// <param name="aliasForm"> /// in case the qual selector results from an alias, /// an x-default node is created if there has not been one. /// </param> /// <returns>Returns the index of th</returns> /// <exception cref="iText.Kernel.XMP.XMPException"></exception> private static int LookupQualSelector(XMPNode arrayNode, String qualName, String qualValue, int aliasForm) { if (XML_LANG.Equals(qualName)) { qualValue = iText.Kernel.XMP.Impl.Utils.NormalizeLangValue(qualValue); int index = XMPNodeUtils.LookupLanguageItem(arrayNode, qualValue); if (index < 0 && (aliasForm & AliasOptions.PROP_ARRAY_ALT_TEXT) > 0) { XMPNode langNode = new XMPNode(ARRAY_ITEM_NAME, null); XMPNode xdefault = new XMPNode(XML_LANG, X_DEFAULT, null); langNode.AddQualifier(xdefault); arrayNode.AddChild(1, langNode); return(1); } else { return(index); } } else { for (int index = 1; index < arrayNode.GetChildrenLength(); index++) { XMPNode currItem = arrayNode.GetChild(index); for (IEnumerator it = currItem.IterateQualifier(); it.MoveNext();) { XMPNode qualifier = (XMPNode)it.Current; if (qualName.Equals(qualifier.GetName()) && qualValue.Equals(qualifier.GetValue() )) { return(index); } } } return(-1); } }