diff options
author | 2016-06-07 14:42:18 +0000 | |
---|---|---|
committer | 2016-06-07 17:53:23 +0000 | |
commit | c6b9b567a5d902446314ad0cf8ad237041ef7b5f (patch) | |
tree | bc957cd1d3e40fd0951372eddcc75d98ec113424 /src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java | |
parent | 133638cf44a6d0428beec12169c205a447f48ec0 (diff) |
Change the readContentsAsString to use the XMLOutputFactory instead of the manual writing.
--
MOS_MIGRATED_REVID=124243184
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java')
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java | 87 |
1 files changed, 51 insertions, 36 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java b/src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java index 9c27f044bd..9267e97d93 100644 --- a/src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java +++ b/src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java @@ -29,6 +29,7 @@ import com.android.resources.ResourceType; import java.io.IOException; import java.io.OutputStream; +import java.io.StringWriter; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; @@ -40,19 +41,22 @@ import java.util.logging.Logger; import javax.annotation.Nullable; import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventFactory; import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.Attribute; import javax.xml.stream.events.Characters; import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.Namespace; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; /** * {@link XmlResourceValues} provides methods for getting {@link XmlResourceValue} derived classes. * - * <p> - * Acts a static factory class containing the general xml parsing logic for resources that are + * <p>Acts a static factory class containing the general xml parsing logic for resources that are * declared inside the <resources> tag. */ public class XmlResourceValues { @@ -74,6 +78,9 @@ public class XmlResourceValues { private static final QName ATTR_PARENT = QName.valueOf("parent"); private static final QName ATTR_TYPE = QName.valueOf("type"); + private static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance(); + private static final XMLEventFactory XML_EVENT_FACTORY = XMLEventFactory.newInstance(); + static final String XLIFF_NAMESPACE = "urn:oasis:names:tc:xliff:document:1.2"; private static final String XLIFF_PREFIX = "xliff"; @@ -160,11 +167,7 @@ public class XmlResourceValues { throws XMLStreamException { // Using a map to deduplicate xmlns declarations on the attributes. Map<String, String> attributeMap = new LinkedHashMap<>(); - @SuppressWarnings({ - "cast", - "unchecked" - }) // The interface returns Iterator, force casting based on documentation. - Iterator<Attribute> attributes = (Iterator<Attribute>) start.getAttributes(); + Iterator<Attribute> attributes = iterateAttributesFrom(start); while (attributes.hasNext()) { Attribute attribute = attributes.next(); QName name = attribute.getName(); @@ -218,40 +221,31 @@ public class XmlResourceValues { @Nullable public static String readContentsAsString(XMLEventReader eventReader, QName startTag) throws XMLStreamException { - StringBuilder contents = new StringBuilder(); + StringWriter contents = new StringWriter(); + XMLEventWriter writer = XML_OUTPUT_FACTORY.createXMLEventWriter(contents); while (!isEndTag(eventReader.peek(), startTag)) { XMLEvent xmlEvent = eventReader.nextEvent(); - if (xmlEvent.isCharacters()) { - contents.append(escapeXmlValues(xmlEvent.asCharacters().getData())); - } else if (xmlEvent.isStartElement()) { + if (xmlEvent.isStartElement()) { // TODO(corysmith): Replace this with a proper representation of the contents that can be // serialized and reconstructed appropriately without modification. - QName name = xmlEvent.asStartElement().getName(); - contents.append("<"); - if (!name.getNamespaceURI().isEmpty()) { - contents - .append(name.getPrefix()) - .append(':') - .append(name.getLocalPart()) - .append(' ') - .append("xmlns:") - .append(name.getPrefix()) - .append("='") - .append(name.getNamespaceURI()) - .append("'"); - } else { - contents.append(name.getLocalPart()); + StartElement start = xmlEvent.asStartElement(); + QName name = start.getName(); + // Lazy with the list for memory usage -- this code path happens a lot. + List<Namespace> namespaces = maybeAddNamespace(name, null); + Iterator<Attribute> attributes = iterateAttributesFrom(start); + while (attributes.hasNext()) { + Attribute attribute = attributes.next(); + namespaces = maybeAddNamespace(attribute.getName(), namespaces); } - contents.append(">"); - } else if (xmlEvent.isEndElement()) { - QName name = xmlEvent.asEndElement().getName(); - contents.append("</"); - if (!name.getNamespaceURI().isEmpty()) { - contents.append(name.getPrefix()).append(':').append(name.getLocalPart()); + if (namespaces != null) { + writer.add( + XML_EVENT_FACTORY.createStartElement( + name, iterateAttributesFrom(start), namespaces.iterator())); } else { - contents.append(name.getLocalPart()); + writer.add(xmlEvent); } - contents.append(">"); + } else { + writer.add(xmlEvent); } } // Verify the end element. @@ -260,6 +254,28 @@ public class XmlResourceValues { return contents.toString(); } + @SuppressWarnings({ + "cast", + "unchecked" + }) // The interface returns Iterator, force casting based on documentation. + private static Iterator<Attribute> iterateAttributesFrom(StartElement start) { + return (Iterator<Attribute>) start.getAttributes(); + } + + private static List<Namespace> maybeAddNamespace(QName name, List<Namespace> namespaces) { + // The xliff namespace is provided by default. + if (name.getNamespaceURI() != null + && !name.getNamespaceURI().isEmpty() + && !(XLIFF_NAMESPACE.equals(name.getNamespaceURI()) + && XLIFF_PREFIX.equals(name.getPrefix()))) { + if (namespaces == null) { + namespaces = new ArrayList<>(); + } + namespaces.add(XML_EVENT_FACTORY.createNamespace(name.getPrefix(), name.getNamespaceURI())); + } + return namespaces; + } + /* XML helper methods follow. */ // TODO(corysmith): Move these to a wrapper class for XMLEventReader. private static String parseReferenceFromElementAttribute( @@ -337,8 +353,7 @@ public class XmlResourceValues { logger.fine( String.format( "Invalid characters [%s] found at %s", - characters.getData(), - characters.getLocation().getLineNumber())); + characters.getData(), characters.getLocation().getLineNumber())); } } return eventReader.nextEvent(); |