Example #1
0
static void StartNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix, XMP_StringPtr uri )
{
    IgnoreParam(userData);

    // As a bug fix hack, change a URI of "http://purl.org/dc/1.1/" to ""http://purl.org/dc/elements/1.1/.
    // Early versions of Flash that put XMP in SWF used a bad URI for the dc: namespace.

    #if XMP_DebugBuild & DumpXMLParseEvents		// Avoid unused variable warning.
        ExpatAdapter * thiz = (ExpatAdapter*)userData;
    #endif

    if ( prefix == 0 ) prefix = "_dflt_";	// Have default namespace.
    if ( uri == 0 ) return;	// Ignore, have xmlns:pre="", no URI to register.

    #if XMP_DebugBuild & DumpXMLParseEvents
        if ( thiz->parseLog != 0 ) {
            PrintIndent ( thiz->parseLog, thiz->elemNesting );
            fprintf ( thiz->parseLog, "StartNamespace: %s - \"%s\"\n", prefix, uri );
        }
    #endif

    if ( XMP_LitMatch ( uri, "http://purl.org/dc/1.1/" ) ) uri = "http://purl.org/dc/elements/1.1/";
    (void) XMPMeta::RegisterNamespace ( uri, prefix, &voidStringPtr, &voidStringLen );

}	// StartNamespaceDeclHandler
Example #2
0
void PhotoDataUtils::ImportIPTC_Array ( const IPTC_Manager & iptc, SXMPMeta * xmp,
										XMP_Uns8 id, const char * xmpNS, const char * xmpProp )
{
	std::string utf8Str;
	size_t count = iptc.GetDataSet ( id, 0 );

	xmp->DeleteProperty ( xmpNS, xmpProp );
	
	XMP_OptionBits arrayForm = kXMP_PropArrayIsUnordered;
	if ( XMP_LitMatch ( xmpNS, kXMP_NS_DC ) && XMP_LitMatch ( xmpProp, "creator" ) ) arrayForm = kXMP_PropArrayIsOrdered;

	for ( size_t ds = 0; ds < count; ++ds ) {
		(void) iptc.GetDataSet_UTF8 ( id, &utf8Str, ds );
		NormalizeToLF ( &utf8Str );
		xmp->AppendArrayItem ( xmpNS, xmpProp, arrayForm, utf8Str.c_str() );
	}

}	// PhotoDataUtils::ImportIPTC_Array
Example #3
0
static void ProcessingInstructionHandler ( void * userData, XMP_StringPtr target, XMP_StringPtr data )
{
    XMP_Assert ( target != 0 );
    ExpatAdapter * thiz = (ExpatAdapter*)userData;

    if ( ! XMP_LitMatch ( target, "xpacket" ) ) return;	// Ignore all PIs except the XMP packet wrapper.
    if ( data == 0 ) data = "";

    #if XMP_DebugBuild & DumpXMLParseEvents
        if ( thiz->parseLog != 0 ) {
            PrintIndent ( thiz->parseLog, thiz->elemNesting );
            fprintf ( thiz->parseLog, "PI: %s - \"%s\"\n", target, data );
        }
    #endif

    XML_Node * parentNode = thiz->parseStack.back();
    XML_Node * piNode  = new XML_Node ( parentNode, target, kPINode );

    piNode->value.assign ( data );
    parentNode->content.push_back ( piNode );

}	// ProcessingInstructionHandler
/* class static */ void
XMPUtils::DuplicateSubtree ( const XMPMeta & source,
							 XMPMeta *		 dest,
							 XMP_StringPtr	 sourceNS,
							 XMP_StringPtr	 sourceRoot,
							 XMP_StringPtr	 destNS,
							 XMP_StringPtr	 destRoot,
							 XMP_OptionBits	 options )
{
	options = options;	// Avoid unused parameter warning.
	
	bool fullSourceTree = false;
	bool fullDestTree   = false;
	
	XMP_ExpandedXPath sourcePath, destPath; 

	const XMP_Node * sourceNode = 0;
	XMP_Node * destNode = 0;
	
	XMP_Assert ( (sourceNS != 0) && (*sourceNS != 0) );
	XMP_Assert ( (sourceRoot != 0) && (*sourceRoot != 0) );
	XMP_Assert ( (dest != 0) && (destNS != 0) && (destRoot != 0) );

	if ( *destNS == 0 )	  destNS   = sourceNS;
	if ( *destRoot == 0 ) destRoot = sourceRoot;
	
	if ( XMP_LitMatch ( sourceNS, "*" ) ) fullSourceTree = true;
	if ( XMP_LitMatch ( destNS, "*" ) )   fullDestTree   = true;
	
	if ( (&source == dest) && (fullSourceTree | fullDestTree) ) {
		XMP_Throw ( "Can't duplicate tree onto itself", kXMPErr_BadParam );
	}
	
	if ( fullSourceTree & fullDestTree ) XMP_Throw ( "Use Clone for full tree to full tree", kXMPErr_BadParam );

	if ( fullSourceTree ) {
	
		// The destination must be an existing empty struct, copy all of the source top level as fields.

		ExpandXPath ( destNS, destRoot, &destPath );
		destNode = FindNode ( &dest->tree, destPath, kXMP_ExistingOnly );

		if ( (destNode == 0) || (! XMP_PropIsStruct ( destNode->options )) ) {
			XMP_Throw ( "Destination must be an existing struct", kXMPErr_BadXPath );
		}
		
		if ( ! destNode->children.empty() ) {
			if ( options & kXMP_DeleteExisting ) {
				destNode->RemoveChildren();
			} else {
				XMP_Throw ( "Destination must be an empty struct", kXMPErr_BadXPath );
			}
		}
		
		for ( size_t schemaNum = 0, schemaLim = source.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) {

			const XMP_Node * currSchema = source.tree.children[schemaNum];

			for ( size_t propNum = 0, propLim = currSchema->children.size(); propNum < propLim; ++propNum ) {
				sourceNode = currSchema->children[propNum];
				XMP_Node * copyNode = new XMP_Node ( destNode, sourceNode->name, sourceNode->value, sourceNode->options );
				destNode->children.push_back ( copyNode );
				CloneOffspring ( sourceNode, copyNode );
			}

		}
	
	} else if ( fullDestTree ) {

		// The source node must be an existing struct, copy all of the fields to the dest top level.

		XMP_ExpandedXPath sourcePath; 
		ExpandXPath ( sourceNS, sourceRoot, &sourcePath );
		sourceNode = FindConstNode ( &source.tree, sourcePath );

		if ( (sourceNode == 0) || (! XMP_PropIsStruct ( sourceNode->options )) ) {
			XMP_Throw ( "Source must be an existing struct", kXMPErr_BadXPath );
		}
		
		destNode = &dest->tree;
		
		if ( ! destNode->children.empty() ) {
			if ( options & kXMP_DeleteExisting ) {
				destNode->RemoveChildren();
			} else {
				XMP_Throw ( "Destination tree must be empty", kXMPErr_BadXPath );
			}
		}
		
		std::string   nsPrefix;
		XMP_StringPtr nsURI;
		XMP_StringLen nsLen;
		
		for ( size_t fieldNum = 0, fieldLim = sourceNode->children.size(); fieldNum < fieldLim; ++fieldNum ) {

			const XMP_Node * currField = sourceNode->children[fieldNum];

			size_t colonPos = currField->name.find ( ':' );
			nsPrefix.assign ( currField->name.c_str(), colonPos );
			bool nsOK = XMPMeta::GetNamespaceURI ( nsPrefix.c_str(), &nsURI, &nsLen );
			if ( ! nsOK ) XMP_Throw ( "Source field namespace is not global", kXMPErr_BadSchema );
			
			XMP_Node * destSchema = FindSchemaNode ( &dest->tree, nsURI, kXMP_CreateNodes );
			if ( destSchema == 0 ) XMP_Throw ( "Failed to find destination schema", kXMPErr_BadSchema );

			XMP_Node * copyNode = new XMP_Node ( destSchema, currField->name, currField->value, currField->options );
			destSchema->children.push_back ( copyNode );
			CloneOffspring ( currField, copyNode );

		}
		
	} else {

		// Find the root nodes for the source and destination subtrees.
		
		ExpandXPath ( sourceNS, sourceRoot, &sourcePath );
		ExpandXPath ( destNS, destRoot, &destPath );
	
		sourceNode = FindConstNode ( &source.tree, sourcePath );
		if ( sourceNode == 0 ) XMP_Throw ( "Can't find source subtree", kXMPErr_BadXPath );
		
		destNode = FindNode ( &dest->tree, destPath, kXMP_ExistingOnly );	// Dest must not yet exist.
		if ( destNode != 0 ) XMP_Throw ( "Destination subtree must not exist", kXMPErr_BadXPath );
		
		destNode = FindNode ( &dest->tree, destPath, kXMP_CreateNodes );	// Now create the dest.
		if ( destNode == 0 ) XMP_Throw ( "Can't create destination root node", kXMPErr_BadXPath );
		
		// Make sure the destination is not within the source! The source can't be inside the destination
		// because the source already existed and the destination was just created.
		
		if ( &source == dest ) {
			for ( XMP_Node * testNode = destNode; testNode != 0; testNode = testNode->parent ) {
				if ( testNode == sourceNode ) {
					// *** delete the just-created dest root node
					XMP_Throw ( "Destination subtree is within the source subtree", kXMPErr_BadXPath );
				}
			}
		}
	
		// *** Could use a CloneTree util here and maybe elsewhere.
		
		destNode->value	  = sourceNode->value;	// *** Should use SetNode.
		destNode->options = sourceNode->options;
		CloneOffspring ( sourceNode, destNode );

	}

}	// DuplicateSubtree