View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.tika.sax;
18  
19  import java.util.Map;
20  import java.util.Collections;
21  import javax.xml.namespace.QName;
22  
23  import org.xml.sax.SAXException;
24  import org.xml.sax.ContentHandler;
25  import org.xml.sax.Attributes;
26  import org.xml.sax.helpers.AttributesImpl;
27  
28  /**
29   * Content handler decorator that maps element <code>QName</code>s using
30   * a <code>Map</code>. Not mappable elements are not forwarded.
31   * Attributes may also be mapped (for each element different using
32   * a <code>Map</code> for attributes), not mappable attributes are not
33   * forwarded. The default is to not map any attributes and therefore do
34   * not forward any of them.
35   */
36  public class ElementMappingContentHandler extends ContentHandlerDecorator {
37  
38      private final Map<QName, TargetElement> mappings;
39  
40      public ElementMappingContentHandler(
41              ContentHandler handler, Map<QName, TargetElement> mappings) {
42          super(handler);
43          this.mappings = mappings;
44      }
45  
46      @Override
47      public void startElement(
48              String namespaceURI, String localName, String qName,
49              Attributes atts) throws SAXException {
50          TargetElement mapping =
51              mappings.get(new QName(namespaceURI, localName));
52          if (mapping != null) {
53              QName tag = mapping.getMappedTagName();
54              super.startElement(
55                      tag.getNamespaceURI(), tag.getLocalPart(),
56                      getQNameAsString(tag), mapping.mapAttributes(atts));
57          }
58      }
59  
60      @Override
61      public void endElement(String namespaceURI, String localName, String qName)
62              throws SAXException {
63          TargetElement mapping =
64              mappings.get(new QName(namespaceURI, localName));
65          if (mapping != null) {
66              QName tag=mapping.getMappedTagName();
67              super.endElement(
68                      tag.getNamespaceURI(), tag.getLocalPart(),
69                      getQNameAsString(tag));
70          }
71      }
72  
73      protected static final String getQNameAsString(QName qname) {
74          String prefix = qname.getPrefix();
75          if (prefix.length() > 0) {
76              return prefix + ":" + qname.getLocalPart();
77          } else {
78              return qname.getLocalPart(); 
79          }
80      }
81  
82      public static class TargetElement {
83  
84          /**
85           * Creates an TargetElement, attributes of this element will
86           * be mapped as specified
87           */
88          public TargetElement(
89                  QName mappedTagName, Map<QName, QName> attributesMapping) {
90              this.mappedTagName = mappedTagName;
91              this.attributesMapping = attributesMapping;
92          }
93  
94          /**
95           * A shortcut that automatically creates the QName object
96           */
97          public TargetElement(
98                  String mappedTagURI, String mappedTagLocalName,
99                  Map<QName, QName> attributesMapping) {
100             this(new QName(mappedTagURI, mappedTagLocalName), attributesMapping);
101         }
102 
103         /**
104          * Creates an TargetElement with no attributes, all attributes
105          * will be deleted from SAX stream
106          */
107         public TargetElement(QName mappedTagName) {
108             this(mappedTagName, Collections.<QName,QName>emptyMap());
109         }
110 
111         /** A shortcut that automatically creates the QName object */
112         public TargetElement(String mappedTagURI, String mappedTagLocalName) {
113             this(mappedTagURI, mappedTagLocalName,
114                     Collections.<QName,QName>emptyMap());
115         }
116 
117         public QName getMappedTagName() {
118             return mappedTagName;
119         }
120 
121         public Map<QName, QName> getAttributesMapping() {
122             return attributesMapping;
123         }
124 
125         public Attributes mapAttributes(final Attributes atts) {
126             AttributesImpl natts = new AttributesImpl();
127             for (int i = 0; i < atts.getLength(); i++) {
128                 QName name = attributesMapping.get(
129                         new QName(atts.getURI(i), atts.getLocalName(i)));
130                 if (name!=null) {
131                     natts.addAttribute(
132                             name.getNamespaceURI(), name.getLocalPart(),
133                             getQNameAsString(name),
134                             atts.getType(i), atts.getValue(i));
135                 }
136             }
137             return natts;
138         }
139 
140         private final QName mappedTagName;
141 
142         private final Map<QName, QName> attributesMapping;
143 
144     }
145 
146 }