Aunque el título sea un poco “extraño”, con este post pretendo explicar un poco como se pueden extraer las etiquetas de metadatos XMP que algunos programas como por ejemplo f-spot introducen para clasificar las fotos.
Esto viene a cuento porque después de clasificar todas las fotos del viaje a NY, algo así como 1200, me he puesto a exportarlas a una carpeta creando una galería web, para hacer más comodo el verlas dentro de un tiempo, y aquí empiezan los problemas, para empezar, el exporter, peta, y para continuar, no te clasifica las fotos por etiquetas, lo cual es una putada bastante decente, así que me he dicho, ¿porque no te haces un programita para hacer esta función? Así que en ello estoy.
Para empezar he empezado con lo más complicado, es decir, como leer los metadatos que el f-spot escribe en las fotos, al final he dado con que los datos XMP, son simplemente un fichero XML embebido en el archivo JPG, el problema viene entonces en como encontrar que fragmento del fichero JPG es que el contiene el XML, pero para esta tarea tenemos al tito google, que trás un par de búsquedas con diferentes términos, un enlace a una página en la que se muestra un fragmento de código que hace precisamente lo que queremos y además, en JAVA xD
El código es el siguiente:
public class XMLExtractor {
public String getXMP(File f) throws IOException {
FileInputStream is = new FileInputStream(f);
int i = 0;
String result = null;
while ((i = is.read()) != -1)
if (i == 0xFF && is.read() == 0xE1) {
result = checkNamespace(is);
if (result != null)
break;
}
return result;
}
public static final String namespace = "http://ns.adobe.com/xap/1.0/";
private String checkNamespace(FileInputStream is) throws IOException {
String s = getSegment(is);
return (s.startsWith(namespace)) ? s.substring(29) : null;
}
private String getSegment(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
byte[] buffer = new byte[dis.readShort() - 2];
dis.read(buffer);
return new String(buffer);
}
}
Lo único que he hecho aquí ha sido mover el método main a otra clase.
Ya tenemos el contenido del XML, ahora solo tenemos que parsearlo para convertirlo en un objeto del tipo “Document” y obtener los datos que nos interesan por medio de operaciones sobre el árbol DOM del XML, para ello, añadimos un nuevo método llamado getTag a la clase anterior. Este método contiene el siguiente código, aunque de momento es solo una aproximación a hacer lo que nos interesa, por lo que puede que cambie bastante en los próximos días
public String getTag(String xml) {
// Converts the XML string to document
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document document = null;
try {
DocumentBuilder builder = factory.newDocumentBuilder(); //el documento
document = builder.parse(new InputSource(new StringReader(xml))); //aqui le paso al Document
} catch(Exception e) {
e.printStackTrace();
}
document.toString();
document.setXmlVersion("1.0");
NodeList list = document.getElementsByTagName("rdf:li");
//NodeList list = document.getChildNodes();
Node node = (Node)list.item(0);
System.out.println(list.getLength()+" - "+node.getFirstChild().getNodeValue());
//XMPMetadata metadata = new XMPMetadata(document);
return node.getFirstChild().getNodeValue();
}
Bueno, de momento, esto es lo que hay, está probado y funciona, aunque como ya digo, este código es de prueba, por lo que solo nos devuelve el valor de la primera etiqueta que encuentra, en caso de que haya varias.
Cuando esté más avanzado el proyecto subiré el código para que se pueda descargar.