📄 xmlparser.java
字号:
parse(is); } /** * Parses XML. * * @param input * Supplies the XML to parse. * * @param rootHandler * The root element handler corresponding to the expected document * type. * * @param rootNamespace * Root element namespace URI. * * @param rootElementName * Root element name. * * @throws IOException * Thrown by {@code input}. * * @throws ParseException * XML failed to validate against the schema implemented by * {@code rootHandler}. */ public void parse(InputStream input, ElementHandler rootHandler, String rootNamespace, String rootElementName) throws IOException, ParseException { InputSource is = new InputSource(input); this.rootHandler = rootHandler; this.rootNamespace = rootNamespace; this.rootElementName = rootElementName; parse(is); } /** * Parses XML. * * @param is * Supplies the XML to parse. * * @throws IOException * Thrown by {@code is}. * * @throws ParseException * XML failed to validate against the schema implemented by * {@code rootHandler}. * * @throws ParserConfigurationException * @throws SAXException */ protected void parse(InputSource is) throws IOException, ParseException { try { // Lazy initialization of the parser factory. There is a minor // init-time race condition here if two parsers are created // simultaneously, but the getSAXParserFactory() impl is thread-safe // and worse case scenario is that multiple parser factories are // initially created during the race. Double-checked locking bug // makes it harder to do better w/out significant overhead. if (parserFactory == null) { parserFactory = getSAXParserFactory(); } SAXParser sp = parserFactory.newSAXParser(); ParserAdapter pa = new ParserAdapter(sp.getParser()); pa.setContentHandler(this); pa.parse(is); } catch (SAXException e) { Exception rootException = e.getException(); if (rootException instanceof ParseException) { throwParseException((ParseException)rootException); } else if (rootException instanceof IOException) { LogUtils.logException(logger, Level.WARNING, null, e); throw (IOException)rootException; } else { LogUtils.logException(logger, Level.WARNING, null, e); throw new ParseException(e); } } catch (ParserConfigurationException e) { LogUtils.logException(logger, Level.WARNING, null, e); throw new ParseException(e); } } /** Throws a parse exception with line/column information. */ private void throwParseException(ParseException e) throws ParseException { if (locator != null) { String elementLocation = ""; if (curHandler != null) { elementLocation += ", element " + curHandler.qName; } String location = "[Line " + String.valueOf(locator.getLineNumber()) + ", Column " + String.valueOf(locator.getColumnNumber()) + elementLocation + "] "; LogUtils.logException(logger, Level.WARNING, location, e); throw new ParseException(location + e.getMessage()); } else { LogUtils.logException(logger, Level.WARNING, null, e); throw e; } } /** * Computes a cumulative value of {@code xml:base} based on a prior value * and a new value. If the new value is an absolute URI, it is returned * unchanged. If the new value is a relative URI, it is combined with the * prior value. * * @param curBase * Current value of {@code xml:base} or {@code null}. * * @param newBase * New value of {@code xml:base}. * * @return Combined value of {@code xml:base}, which is guaranteed to be * an absolute URI. * * @throws URISyntaxException * Invalid value of {@code xml:base} (doesn't parse as a valid * relative/absolute URI depending on {@code xml:base} context). */ static String getCumulativeXmlBase(String curBase, String newBase) throws URISyntaxException { URI newBaseUri = new URI(newBase); if (curBase == null || curBase.equals("")) { // We require an absolute URI. if (!newBaseUri.isAbsolute()) { throw new URISyntaxException( newBase, "No xml:base established--need an absolute URI."); } return newBase; } URI curBaseUri = new URI(curBase); URI resultUri = curBaseUri.resolve(newBaseUri); assert resultUri.isAbsolute(); return resultUri.toString(); } /** SAX callback. */ public void startElement(String namespace, String localName, String qName, Attributes attrs) throws SAXException { logger.fine("Start element " + qName); ElementHandler parentHandler = curHandler; if (curHandler == null && namespace.equals(rootNamespace) && localName.equals(rootElementName)) { curHandler = rootHandler; } else if (curHandler != null && unrecognizedElements == 0) { try { curHandler = curHandler.getChildHandler(namespace, localName, attrs); } catch (ParseException e) { throw new SAXException(e); } catch (IOException e) { throw new SAXException(e); } } if (curHandler != null && unrecognizedElements == 0) { curHandler.parent = parentHandler; curHandler.qName = qName; // Propagate xml:lang and xml:base. if (parentHandler != null) { curHandler.xmlLang = parentHandler.xmlLang; curHandler.xmlBase = parentHandler.xmlBase; } try { // First pass to extract xml:lang and xml:base. for (int i = attrs.getLength() - 1; i >= 0; --i) { String attrNamespace = attrs.getURI(i); String attrLocalName = attrs.getLocalName(i); String attrValue = attrs.getValue(i); if (attrNamespace.equals("http://www.w3.org/XML/1998/namespace")) { if (attrLocalName.equals("lang")) { curHandler.xmlLang = attrValue; logger.finer("xml:lang=" + attrValue); } else if (attrLocalName.equals("base")) { curHandler.xmlBase = getCumulativeXmlBase(curHandler.xmlBase, attrValue); logger.finer("xml:base=" + curHandler.xmlBase); } } } // Second pass to process attributes. for (int i = attrs.getLength() - 1; i >= 0; --i) { String attrNamespace = attrs.getURI(i); String attrLocalName = attrs.getLocalName(i); String attrValue = attrs.getValue(i); logger.finer("Attribute " + attrLocalName + "='" + attrValue + "'"); curHandler.processAttribute(attrNamespace, attrLocalName, attrValue); } } catch (ParseException e) { throw new SAXException(e); } catch (URISyntaxException e) { throw new SAXException(new ParseException(e.getMessage())); } catch (NumberFormatException e) { throw new SAXException( new ParseException("Invalid integer format. " + e.getMessage())); } // If the current handler accepts random XML, process the state acquired // so far. curHandler.okToInitializeXmlBlob = false; if (curHandler.xmlBlob != null) { // Store xml:lang and xml:base state, if any. if (curHandler.xmlLang != null) { curHandler.xmlBlob.setLang(curHandler.xmlLang); } if (curHandler.xmlBase != null) { curHandler.xmlBlob.setBase(curHandler.xmlBase); } } } else { // curHandler == null || unrecognizedElements > 0 ++unrecognizedElements; if (curHandler == null) { curHandler = parentHandler; } // This element hasn't been recognized by the handler. // If the handler allows foreign XML, we'll start accumulating it as // a string. if (curHandler != null && curHandler.innerXml != null) { ArrayList<XmlWriter.Attribute> attrList = new ArrayList<XmlWriter.Attribute>(attrs.getLength()); for (int i = attrs.getLength() - 1; i >= 0; --i) { String qNameAttr = attrs.getQName(i); ensureBlobNamespace(curHandler, qNameAttr); String value = attrs.getValue(i); XmlWriter.Attribute attr = new XmlWriter.Attribute(qNameAttr, value); attrList.add(attr); if (curHandler.fullTextIndex) { curHandler.fullTextIndexWriter.write(value); curHandler.fullTextIndexWriter.write(" "); } } try { ensureBlobNamespace(curHandler, qName); curHandler.innerXml.startElement(null, qName, attrList, namespaceDecls); } catch (IOException e) { throw new SAXException(e); } } } // Make way for next element's state. namespaceDecls.clear(); } /** SAX callback. */ public void endElement(String namespace, String localName, String qName) throws SAXException { logger.fine("End element " + qName); if (unrecognizedElements > 0) { --unrecognizedElements; if (curHandler != null && curHandler.innerXml != null) { try { curHandler.innerXml.endElement(); } catch (IOException e) { throw new SAXException(e); } } } else if (curHandler != null) { if (curHandler.xmlBlob != null) { curHandler.xmlBlob.setBlob(curHandler.innerXmlStringWriter.toString()); if (curHandler.fullTextIndex) { curHandler.xmlBlob.setFullText( curHandler.fullTextIndexWriter.toString()); } } try { curHandler.processEndElement(); } catch (ParseException e) { throw new SAXException(e); } curHandler = curHandler.parent; } } /** SAX callback. */ public void characters(char[] text, int start, int len) throws SAXException { if (curHandler != null) { if (unrecognizedElements == 0) { if (curHandler.value == null) { curHandler.value = new String(); } curHandler.value += new String(text, start, len); } if (curHandler.innerXml != null && (curHandler.mixedContent || unrecognizedElements > 0)) { if (curHandler.fullTextIndex) { curHandler.fullTextIndexWriter.write(text, start, len); curHandler.fullTextIndexWriter.write("\n"); } try { curHandler.innerXml.characters(new String(text, start, len)); } catch (IOException e) { throw new SAXException(e); } } } } /** SAX callback. */ public void ignorableWhitespace(char[] text, int start, int len) throws SAXException { if (curHandler != null && curHandler.innerXml != null && (curHandler.mixedContent || unrecognizedElements > 0)) { try { curHandler.innerXml.writeUnescaped(new String(text, start, len)); } catch (IOException e) { throw new SAXException(e); } } } /** SAX callback. */ public void setDocumentLocator(Locator locator) { this.locator = locator; } /** SAX callback. */ public void startPrefixMapping(String alias, String uri) { Stack<XmlWriter.Namespace> mapping = namespaceMap.get(alias); if (mapping == null) { mapping = new Stack<XmlWriter.Namespace>(); namespaceMap.put(alias, mapping); } XmlWriter.Namespace ns = new XmlWriter.Namespace(alias, uri); mapping.push(ns); namespaceDecls.add(ns); } /** SAX callback. */ public void endPrefixMapping(String alias) { namespaceMap.get(alias).pop(); } /** Ensures that the namespace from the QName is stored with the blob. */ private void ensureBlobNamespace(ElementHandler handler, String qName) { // Get the namespace. XmlWriter.Namespace ns = null; String alias = qName.substring(0, Math.max(0, qName.indexOf(":"))); if (alias.equals("xml")) { // "xml:" doesn't need a declaration. return; } Stack<XmlWriter.Namespace> mapping = namespaceMap.get(alias); if (mapping != null) { ns = mapping.peek(); } // The namespace might be null for a namespace-less element. assert alias.length() == 0 || ns != null : "Namespace alias '" + alias + "' should be mapped in 'namespaceMap'."; // Make sure the namespace described within the blob. if (ns != null && !handler.blobNamespaces.contains(alias)) { handler.blobNamespaces.add(alias); handler.xmlBlob.namespaces.add(new XmlNamespace(alias, ns.getUri())); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -