📄 xmpserializerrdf.java
字号:
{ XMPNode qualifier = (XMPNode) it.next(); declareNamespace(qualifier.getName(), null, usedPrefixes, indent); declareUsedNamespaces(qualifier, usedPrefixes, indent); } } /** * Writes one namespace declaration to the output. * @param prefix a namespace prefix (without colon) or a complete qname (when namespace == null) * @param namespace the a namespace * @param usedPrefixes a set containing currently used prefixes * @param indent the current indent level * @throws IOException Forwards all writer exceptions. */ private void declareNamespace(String prefix, String namespace, Set usedPrefixes, int indent) throws IOException { if (namespace == null) { // prefix contains qname, extract prefix and lookup namespace with prefix QName qname = new QName(prefix); if (qname.hasPrefix()) { prefix = qname.getPrefix(); // add colon for lookup namespace = XMPMetaFactory.getSchemaRegistry().getNamespaceURI(prefix + ":"); // prefix w/o colon declareNamespace(prefix, namespace, usedPrefixes, indent); } else { return; } } if (!usedPrefixes.contains(prefix)) { writeNewline(); writeIndent(indent); write("xmlns:"); write(prefix); write("=\""); write(namespace); write('"'); usedPrefixes.add(prefix); } } /** * Recursively handles the "value" for a node. It does not matter if it is a * top level property, a field of a struct, or an item of an array. The * indent is that for the property element. An xml:lang qualifier is written * as an attribute of the property start tag, not by itself forcing the * qualified property form. The patterns below mostly ignore attribute * qualifiers like xml:lang. Except for the one struct case, attribute * qualifiers don't affect the output form. * * <blockquote> * * <pre> * <ns:UnqualifiedSimpleProperty>value</ns:UnqualifiedSimpleProperty> * * <ns:UnqualifiedStructProperty rdf:parseType="Resource"> * (If no rdf:resource qualifier) * ... Fields, same forms as top level properties * </ns:UnqualifiedStructProperty> * * <ns:ResourceStructProperty rdf:resource="URI" * ... Fields as attributes * > * * <ns:UnqualifiedArrayProperty> * <rdf:Bag> or Seq or Alt * ... Array items as rdf:li elements, same forms as top level properties * </rdf:Bag> * </ns:UnqualifiedArrayProperty> * * <ns:QualifiedProperty rdf:parseType="Resource"> * <rdf:value> ... Property "value" following the unqualified * forms ... </rdf:value> * ... Qualifiers looking like named struct fields * </ns:QualifiedProperty> * </pre> * * </blockquote> * * @param node the property node * @param emitAsRDFValue property shall be renderes as attribute rather than tag * @param indent the current indent level * @throws IOException Forwards all writer exceptions. * @throws XMPException If "rdf:resource" and general qualifiers are mixed. */ private void serializePrettyRDFProperty(XMPNode node, boolean emitAsRDFValue, int indent) throws IOException, XMPException { boolean emitEndTag = true; boolean indentEndTag = true; // Determine the XML element name. Open the start tag with the name and // attribute qualifiers. String elemName = node.getName(); if (emitAsRDFValue) { elemName = "rdf:value"; } else if (XMPConst.ARRAY_ITEM_NAME.equals(elemName)) { elemName = "rdf:li"; } writeIndent(indent); write('<'); write(elemName); boolean isCompact = node.getOptions().isCompact(); boolean hasGeneralQualifiers = isCompact; // Might also become true later. boolean hasRDFResourceQual = false; for (Iterator it = node.iterateQualifier(); it.hasNext();) { XMPNode qualifier = (XMPNode) it.next(); if (!RDF_ATTR_QUALIFIER.contains(qualifier.getName())) { hasGeneralQualifiers = true; } else { hasRDFResourceQual = "rdf:resource".equals(qualifier.getName()); if (!emitAsRDFValue) { write(' '); write(qualifier.getName()); write("=\""); appendNodeValue(qualifier.getValue(), true); write('"'); } } } // Process the property according to the standard patterns. if (hasGeneralQualifiers && !emitAsRDFValue) { // This node has general, non-attribute, qualifiers. Emit using the // qualified property form. // ! The value is output by a recursive call ON THE SAME NODE with // emitAsRDFValue set. if (hasRDFResourceQual) { throw new XMPException("Can't mix rdf:resource and general qualifiers", XMPError.BADRDF); } write(" rdf:parseType=\"Resource\">"); writeNewline(); serializePrettyRDFProperty(node, true, indent + 1); if (isCompact) { // Emit a "pxmp:compact" fake qualifier. writeIndent(indent); write("<pxmp:compact/>"); writeNewline(); } for (Iterator it = node.iterateQualifier(); it.hasNext();) { XMPNode qualifier = (XMPNode) it.next(); if (!RDF_ATTR_QUALIFIER.contains(qualifier.getName())) { serializePrettyRDFProperty(qualifier, false, indent + 1); } } } else { // This node has no general qualifiers. Emit using an unqualified form. if (!node.getOptions().isCompositeProperty()) { // This is a simple property. if (node.getOptions().isURI()) { write(" rdf:resource=\""); appendNodeValue(node.getValue(), true); write("\"/>"); writeNewline(); emitEndTag = false; } else if (node.getValue() == null || "".equals(node.getValue())) { write("/>"); writeNewline(); emitEndTag = false; } else { write('>'); appendNodeValue(node.getValue(), false); indentEndTag = false; } } else if (node.getOptions().isArray()) { // This is an array. write('>'); writeNewline(); emitRDFArrayTag(node, true, indent + 1); if (node.getOptions().isArrayAltText()) { XMPNodeUtils.normalizeLangArray(node); } for (Iterator it = node.iterateChildren(); it.hasNext();) { XMPNode child = (XMPNode) it.next(); serializePrettyRDFProperty(child, false, indent + 2); } emitRDFArrayTag(node, false, indent + 1); } else if (!hasRDFResourceQual) { // This is a "normal" struct, use the rdf:parseType="Resource" form. if (!node.hasChildren()) { write(" rdf:parseType=\"Resource\"/>"); writeNewline(); emitEndTag = false; } else { write(" rdf:parseType=\"Resource\">"); writeNewline(); for (Iterator it = node.iterateChildren(); it.hasNext();) { XMPNode child = (XMPNode) it.next(); serializePrettyRDFProperty(child, false, indent + 1); } } } else { // This is a struct with an rdf:resource attribute, use the // "empty property element" form. for (Iterator it = node.iterateChildren(); it.hasNext();) { XMPNode child = (XMPNode) it.next(); if (!canBeRDFAttrProp(child)) { throw new XMPException("Can't mix rdf:resource and complex fields", XMPError.BADRDF); } writeNewline(); writeIndent(indent + 1); write(' '); write(child.getName()); write("=\""); appendNodeValue(child.getValue(), true); write('"'); } write("/>"); writeNewline(); emitEndTag = false; } } // Emit the property element end tag. if (emitEndTag) { if (indentEndTag) { writeIndent(indent); } write("</"); write(elemName); write('>'); writeNewline(); } } /** * Writes the array start and end tags. * * @param arrayNode an array node * @param isStartTag flag if its the start or end tag * @param indent the current indent level * @throws IOException forwards writer exceptions */ private void emitRDFArrayTag(XMPNode arrayNode, boolean isStartTag, int indent) throws IOException { if (isStartTag || arrayNode.hasChildren()) { writeIndent(indent); write(isStartTag ? "<rdf:" : "</rdf:"); if (arrayNode.getOptions().isArrayAlternate()) { write("Alt"); } else if (arrayNode.getOptions().isArrayOrdered()) { write("Seq"); } else { write("Bag"); } if (isStartTag && !arrayNode.hasChildren()) { write("/>"); } else { write(">"); } writeNewline(); } } /** * Serializes the node value in XML encoding. Its used for tag bodies and * attributes. <em>Note:</em> The attribute is always limited by quotes, * thats why <code>&apos;</code> is never serialized. <em>Note:</em> * Control chars are written unescaped, but if the user uses others than tab, LF * and CR the resulting XML will become invalid. * * @param value the value of the node * @param forAttribute flag if value is an attribute value * @throws IOException */ private void appendNodeValue(String value, boolean forAttribute) throws IOException { write (Utils.escapeXML(value, forAttribute, true)); } /** * A node can be serialized as RDF-Attribute, if it meets the following conditions: * <ul> * <li>is not array item * <li>don't has qualifier * <li>is no URI * <li>is no composite property * </ul> * * @param node an XMPNode * @return Returns true if the node serialized as RDF-Attribute */ private boolean canBeRDFAttrProp(XMPNode node) { return !node.hasQualifier() && !node.getOptions().isURI() && !node.getOptions().isCompositeProperty() && !XMPConst.ARRAY_ITEM_NAME.equals(node.getName()); } /** * Writes indents and automatically includes the baseindend from the options. * @param times number of indents to write * @throws IOException forwards exception */ private void writeIndent(int times) throws IOException { for (int i = options.getBaseIndent() + times; i > 0; i--) { writer.write(options.getIndent()); } } /** * Writes a char to the output. * @param c a char * @throws IOException forwards writer exceptions */ private void write(int c) throws IOException { writer.write(c); } /** * Writes a String to the output. * @param str a String * @throws IOException forwards writer exceptions */ private void write(String str) throws IOException { writer.write(str); } /** * Writes an amount of chars, mostly spaces * @param number number of chars * @param c a char * @throws IOException */ private void writeChars(int number, char c) throws IOException { for (; number > 0; number--) { writer.write(c); } } /** * Writes a newline according to the options. * @throws IOException Forwards exception */ private void writeNewline() throws IOException { writer.write(options.getNewline()); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -