📄 xmpserializerrdf.java
字号:
} } return allAreAttrs; } /** * Recursively handles the "value" for a node that must be written as an RDF * property element. 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. The patterns bwlow ignore attribute qualifiers such as * xml:lang, they don't affect the output form. * * <blockquote> * * <pre> * <ns:UnqualifiedStructProperty-1 * ... The fields as attributes, if all are simple and unqualified * /> * * <ns:UnqualifiedStructProperty-2 rdf:parseType="Resource"> * ... The fields as elements, if none are simple and unqualified * </ns:UnqualifiedStructProperty-2> * * <ns:UnqualifiedStructProperty-3> * <rdf:Description * ... The simple and unqualified fields as attributes * > * ... The compound or qualified fields as elements * </rdf:Description> * </ns:UnqualifiedStructProperty-3> * * <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> * * *** Consider numbered array items, but has compatibility problems. *** * Consider qualified form with rdf:Description and attributes. * * @param parentNode the parent node * @param indent the current indent level * @throws IOException Forwards writer exceptions * @throws XMPException If qualifier and element fields are mixed. */ private void serializeCompactRDFElementProps(XMPNode parentNode, int indent) throws IOException, XMPException { for (Iterator it = parentNode.iterateChildren(); it.hasNext();) { XMPNode node = (XMPNode) it.next(); if (canBeRDFAttrProp (node)) { continue; } boolean emitEndTag = true; boolean indentEndTag = true; // Determine the XML element name, write the name part of the start tag. Look over the // qualifiers to decide on "normal" versus "rdf:value" form. Emit the attribute // qualifiers at the same time. String elemName = node.getName(); 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 iq = node.iterateQualifier(); iq.hasNext();) { XMPNode qualifier = (XMPNode) iq.next(); if (!RDF_ATTR_QUALIFIER.contains(qualifier.getName())) { hasGeneralQualifiers = true; } else { hasRDFResourceQual = "rdf:resource".equals(qualifier.getName()); write(' '); write(qualifier.getName()); write("=\""); appendNodeValue(qualifier.getValue(), true); write('"'); } } // Process the property according to the standard patterns. if (hasGeneralQualifiers) { serializeCompactRDFGeneralQualifier(indent, node, isCompact); } else { // This node has only attribute qualifiers. Emit as a property element. if (!node.getOptions().isCompositeProperty()) { Object[] result = serializeCompactRDFSimpleProp(node); emitEndTag = ((Boolean) result[0]).booleanValue(); indentEndTag = ((Boolean) result[1]).booleanValue(); } else if (node.getOptions().isArray()) { serializeCompactRDFArrayProp(node, indent); } else { emitEndTag = serializeCompactRDFStructProp( node, indent, hasRDFResourceQual); } } // Emit the property element end tag. if (emitEndTag) { if (indentEndTag) { writeIndent(indent); } write("</"); write(elemName); write('>'); writeNewline(); } } } /** * Serializes a simple property. * * @param node an XMPNode * @return Returns an array containing the flags emitEndTag and indentEndTag. * @throws IOException Forwards the writer exceptions. */ private Object[] serializeCompactRDFSimpleProp(XMPNode node) throws IOException { // This is a simple property. Boolean emitEndTag = Boolean.TRUE; Boolean indentEndTag = Boolean.TRUE; if (node.getOptions().isURI()) { write(" rdf:resource=\""); appendNodeValue(node.getValue(), true); write("\"/>"); writeNewline(); emitEndTag = Boolean.FALSE; } else if (node.getValue() == null || node.getValue().length() == 0) { write("/>"); writeNewline(); emitEndTag = Boolean.FALSE; } else { write('>'); appendNodeValue (node.getValue(), false); indentEndTag = Boolean.FALSE; } return new Object[] {emitEndTag, indentEndTag}; } /** * Serializes an array property. * * @param node an XMPNode * @param indent the current indent level * @throws IOException Forwards the writer exceptions. * @throws XMPException If qualifier and element fields are mixed. */ private void serializeCompactRDFArrayProp(XMPNode node, int indent) throws IOException, XMPException { // This is an array. write('>'); writeNewline(); emitRDFArrayTag (node, true, indent + 1); if (node.getOptions().isArrayAltText()) { XMPNodeUtils.normalizeLangArray (node); } serializeCompactRDFElementProps(node, indent + 2); emitRDFArrayTag(node, false, indent + 1); } /** * Serializes a struct property. * * @param node an XMPNode * @param indent the current indent level * @param hasRDFResourceQual Flag if the element has resource qualifier * @return Returns true if an end flag shall be emitted. * @throws IOException Forwards the writer exceptions. * @throws XMPException If qualifier and element fields are mixed. */ private boolean serializeCompactRDFStructProp(XMPNode node, int indent, boolean hasRDFResourceQual) throws XMPException, IOException { // This must be a struct. boolean hasAttrFields = false; boolean hasElemFields = false; boolean emitEndTag = true; for (Iterator ic = node.iterateChildren(); ic.hasNext(); ) { XMPNode field = (XMPNode) ic.next(); if (canBeRDFAttrProp(field)) { hasAttrFields = true; } else { hasElemFields = true; } if (hasAttrFields && hasElemFields) { break; // No sense looking further. } } if (hasRDFResourceQual && hasElemFields) { throw new XMPException( "Can't mix rdf:resource qualifier and element fields", XMPError.BADRDF); } if (!node.hasChildren()) { // Catch an empty struct as a special case. The case // below would emit an empty // XML element, which gets reparsed as a simple property // with an empty value. write(" rdf:parseType=\"Resource\"/>"); writeNewline(); emitEndTag = false; } else if (!hasElemFields) { // All fields can be attributes, use the // emptyPropertyElt form. serializeCompactRDFAttrProps(node, indent + 1); write("/>"); writeNewline(); emitEndTag = false; } else if (!hasAttrFields) { // All fields must be elements, use the // parseTypeResourcePropertyElt form. write(" rdf:parseType=\"Resource\">"); writeNewline(); serializeCompactRDFElementProps(node, indent + 1); } else { // Have a mix of attributes and elements, use an inner rdf:Description. write('>'); writeNewline(); writeIndent(indent + 1); write(RDF_STRUCT_START); serializeCompactRDFAttrProps(node, indent + 2); write(">"); writeNewline(); serializeCompactRDFElementProps(node, indent + 1); writeIndent(indent + 1); write(RDF_STRUCT_END); writeNewline(); } return emitEndTag; } /** * Serializes the general qualifier. * @param node the root node of the subtree * @param indent the current indent level * @param isCompact flag if qual shall be renderen in compact form. * @throws IOException Forwards all writer exceptions. * @throws XMPException If qualifier and element fields are mixed. */ private void serializeCompactRDFGeneralQualifier(int indent, XMPNode node, boolean isCompact) throws IOException, XMPException { // The node has general qualifiers, ones that can't be // attributes on a property element. // Emit using the qualified property pseudo-struct form. The // value is output by a call // to SerializePrettyRDFProperty with emitAsRDFValue set. write(" rdf:parseType=\"Resource\">"); writeNewline(); serializePrettyRDFProperty(node, true, indent + 1); if (isCompact) { // Emit a "pxmp:compact" fake qualifier. writeIndent(1); write("<pxmp:compact/>"); writeNewline(); } for (Iterator iq = node.iterateQualifier(); iq.hasNext();) { XMPNode qualifier = (XMPNode) iq.next(); serializePrettyRDFProperty(qualifier, false, indent + 1); } } /** * Serializes one schema with all contained properties in pretty-printed * manner.<br> * Each schema's properties are written in a separate * rdf:Description element. All of the necessary namespaces are declared in * the rdf:Description element. The baseIndent is the base level for the * entire serialization, that of the x:xmpmeta element. An xml:lang * qualifier is written as an attribute of the property start tag, not by * itself forcing the qualified property form. * * <blockquote> * * <pre> * <rdf:Description rdf:about="TreeName" xmlns:ns="URI" ... > * * ... The actual properties of the schema, see SerializePrettyRDFProperty * * <!-- ns1:Alias is aliased to ns2:Actual --> ... If alias comments are wanted * * </rdf:Description> * </pre> * * </blockquote> * * @param schemaNode a schema node * @throws IOException Forwarded writer exceptions * @throws XMPException */ private void serializePrettyRDFSchema(XMPNode schemaNode) throws IOException, XMPException { writeIndent(2); write(RDF_SCHEMA_START); writeTreeName(); Set usedPrefixes = new HashSet(); usedPrefixes.add("xml"); usedPrefixes.add("rdf"); declareUsedNamespaces(schemaNode, usedPrefixes, 4); write('>'); writeNewline(); // Write each of the schema's actual properties. for (Iterator it = schemaNode.iterateChildren(); it.hasNext();) { XMPNode propNode = (XMPNode) it.next(); serializePrettyRDFProperty(propNode, false, 3); } // Write the rdf:Description end tag. writeIndent(2); write(RDF_SCHEMA_END); writeNewline(); } /** * Writes all used namespaces of the subtree in node to the output. * The subtree is recursivly traversed. * @param node the root node of the subtree * @param usedPrefixes a set containing currently used prefixes * @param indent the current indent level * @throws IOException Forwards all writer exceptions. */ private void declareUsedNamespaces(XMPNode node, Set usedPrefixes, int indent) throws IOException { if (node.getOptions().isSchemaNode()) { // The schema node name is the URI, the value is the prefix. String prefix = node.getValue().substring(0, node.getValue().length() - 1); declareNamespace(prefix, node.getName(), usedPrefixes, indent); } else if (node.getOptions().isStruct()) { for (Iterator it = node.iterateChildren(); it.hasNext();) { XMPNode field = (XMPNode) it.next(); declareNamespace(field.getName(), null, usedPrefixes, indent); } } for (Iterator it = node.iterateChildren(); it.hasNext();) { XMPNode child = (XMPNode) it.next(); declareUsedNamespaces(child, usedPrefixes, indent); } for (Iterator it = node.iterateQualifier(); it.hasNext();)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -