org.apache.tika.parser.xml.XMLProfiler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tika.parser.xml;
import org.apache.commons.io.input.CloseShieldInputStream;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.Property;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AbstractParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.OfflineContentHandler;
import org.apache.tika.utils.XMLReaderUtils;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
/**
*
*
* This parser enables profiling of XML. It captures the root entity as well as
* entity uris/namespaces and entity local names in parallel arrays.
*
*
*
* This parser is not part of the default set of parsers and must be "turned on"
* via a tika config:
*
* <properties>
* <parsers>
* <parser class="org.apache.tika.parser.DefaultParser"/>
* <parser class="org.apache.tika.parser.xml.XMLProfiler"/>
* </parsers>
* </properties>
*
*
* This was initially designed to profile xmp and xfa in PDFs. Further
* work would need to be done to extract other types of xml and/or
* xmp in other file formats. Please open a ticket.
*
*/
public class XMLProfiler extends AbstractParser {
public static Property ROOT_ENTITY = Property.internalText("xmlprofiler:root_entity");
public static Property ENTITY_URIS = Property.internalTextBag("xmlprofiler:entity_uris");
public static Property ENTITY_LOCAL_NAMES = Property.internalTextBag("xmlprofiler:entity_local_names");
private static final Set SUPPORTED_TYPES =
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
MediaType.application("xml"),
//https://wwwimages2.adobe.com/content/dam/acom/en/devnet/xmp/pdfs/XMP%20SDK%20Release%20cc-2016-08/XMPSpecificationPart3.pdf
//"If a MIME type is needed, use application/rdf+xml."
MediaType.application("rdf+xml"),//xmp
//xfa: https://en.wikipedia.org/wiki/XFA
MediaType.application("vnd.adobe.xdp+xml")
)));
@Override
public Set getSupportedTypes(ParseContext context) {
return SUPPORTED_TYPES;
}
@Override
public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context)
throws IOException, SAXException, TikaException {
XMLReaderUtils.parseSAX(
new CloseShieldInputStream(stream),
new OfflineContentHandler(new XMLProfileHandler(metadata)), context);
}
private static class XMLProfileHandler extends DefaultHandler {
private final Metadata metadata;
int starts = 0;
Map entities = new TreeMap<>();
public XMLProfileHandler(Metadata metadata) {
this.metadata = metadata;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if (starts == 0) {
metadata.set(ROOT_ENTITY, qName);
}
Set localNames = entities.get(uri);
if (localNames == null) {
localNames = new TreeSet<>();
entities.put(uri, localNames);
}
localNames.add(localName);
starts++;
}
@Override
public void endDocument() throws SAXException {
String[] uris = new String[entities.size()];
String[] localNames = new String[entities.size()];
int i = 0;
for (Map.Entry e : entities.entrySet()) {
uris[i] = e.getKey();
localNames[i] = joinWith(" ", e.getValue());
i++;
}
metadata.set(ENTITY_URIS, uris);
metadata.set(ENTITY_LOCAL_NAMES, localNames);
}
static String joinWith(String delimiter, Collection strings) {
StringBuilder sb = new StringBuilder();
int i = 0;
for (String s : strings) {
if (i > 0) {
sb.append(delimiter);
}
sb.append(s);
i++;
}
return sb.toString();
}
}
}