parser2.java
来自「java jdk 1.4的源码」· Java 代码 · 共 1,790 行 · 第 1/5 页
JAVA
1,790 行
// CHAPTER 3: Logical Structures // private boolean maybeElement (ElementValidator validator) throws IOException, SAXException { // [39] element ::= EmptyElemTag | Stag content ETag // [40] STag ::= '<' Name (S Attribute)* S? '>' NameCacheEntry name; ElementDecl element; boolean haveAttributes = false; boolean hasContent = true; int startLine; // the leading "<" has already been consumed name = maybeGetNameCacheEntry (); // n.b. InputEntity guarantees 1+N char pushback always, // and maybeGetName won't use more than one to see if // it's instead "<?", "<!--", "<![CDATA[", or an error. if (name == null) return false; // XXX Test for namespace conformance here // if (namespaces) { // some code testing name.name // } // report validity errors ASAP if (validator != null) validator.consume (name.name); element = (ElementDecl) elements.get (name.name); if (supportValidation && isValidating) { if (element == null || element.contentType == null) { error ("V-005", new Object [] { name.name }); // minimize repetitive diagnostics element = new ElementDecl (name.name); element.contentType = strANY; elements.put (name.name, element); } if (validator == null && rootElementName != null && !rootElementName.equals (name.name)) error ("V-006", new Object [] { name.name, rootElementName }); } // save the line number here so we can give better diagnostics // by identifying where the element started; WF errors may be // reported thousands of lines "late". startLine = in.getLineNumber (); // Invariant: attTmp and nsAttTmp are empty except briefly in this // method they are not empty iff haveAttributes is true // Track whether we saw whitespace before an attribute; // in some cases it's required, though superfluous boolean sawWhite = in.maybeWhitespace (); // These are exceptions from the first pass; they should be ignored // if there's a second pass, but reported otherwise. A second pass // occurs when a namespace declaration is found in the first pass. Vector exceptions = null; // SAX2 Namespace processing if (namespaces) { nsSupport.pushContext(); seenNSDecl = false; } // Each pass through this loop reads // Name eq AttValue S? // Loop exits on ">", "/>", or error for (;;) { if (in.peekc ('>')) break; // [44] EmptyElementTag ::= '<' Name (S Attribute)* S? '/>' if (in.peekc ('/')) { hasContent = false; break; } //Need to have a whitespace between attributes. if (!sawWhite) fatal ("P-030"); // [41] Attribute ::= Name Eq AttValue String attQName; AttributeDecl info; String value; attQName = maybeGetName (); // Need to do this as we have already consumed the // whitespace and didn't see the end tag. if (attQName == null) fatal ("P-031", new Object [] { new Character (getc ()) }); if (attTmp.getValue (attQName) != null) fatal ("P-032", new Object [] { attQName }); // [25] Eq ::= S? '=' S? in.maybeWhitespace (); nextChar ('=', "F-026", attQName); in.maybeWhitespace (); // We are not in the DTD => PEs are not recognized => we no // longer need to expand PEs => don't expand PEs in AttValue => // doLexicalPE = false and call parseLiteral(isEntityValue = // false) both doLexicalPE = false; parseLiteral (false); // We are no longer in the DTD so we never need to expand PEs sawWhite = in.maybeWhitespace (); // normalize and check values right away. info = (element == null) ? null : (AttributeDecl) element.attributes.get (attQName); if (info == null) { if (supportValidation && isValidating) error ("V-007", new Object [] { attQName, name.name }); value = strTmp.toString (); } else { if (!AttributeDecl.CDATA.equals (info.type)) { value = normalize (!info.isFromInternalSubset); if (supportValidation && isValidating) validateAttributeSyntax (info, value); } else value = strTmp.toString (); if (supportValidation && isValidating && info.isFixed && !value.equals (info.defaultValue)) error ("V-008", new Object [] {attQName, name.name, info.defaultValue}); } // assert(value != null) if (XmlLang.equals (attQName) && !isXmlLang (value)) error ("P-033", new Object [] { value }); String type = (info == null) ? AttributeDecl.CDATA : info.type; String defaultValue = (info == null) ? null : info.defaultValue; if (namespaces) { exceptions = processAttributeNS(attQName, type, value, defaultValue, true, false, exceptions); } else { // No namespaces case attTmp.addAttribute("", "", attQName, type, value, defaultValue, true); } haveAttributes = true; } if (element != null) attTmp.setIdAttributeName (element.id); // if we had ATTLIST decls, handle required & defaulted attributes // before telling next layer about this element if (element != null && element.attributes.size () != 0) { haveAttributes = defaultAttributes(element) || haveAttributes; } // Ensure that this element's namespace declarations apply to all of // this element's attributes as well. If there was a Namespace // declaration, we have to make a second pass just to be safe -- this // will happen very rarely, possibly only once for each document. if (seenNSDecl) { // assert(namespaces == true) int length = attTmp.getLength(); for (int i = 0; i < length; i++) { String attQName = attTmp.getQName(i); if (attQName.startsWith("xmlns")) { // Could be a namespace declaration if (attQName.length() == 5 || attQName.charAt(5) == ':') { // Default or non-default NS declaration continue; } } // assert(not a namespace declaration) String attName[] = processName(attQName, true, false); attTmp.setURI(i, attName[0]); attTmp.setLocalName(i, attName[1]); } } else if (exceptions != null && errHandler != null) { for (int i = 0; i < exceptions.size(); i++) { errHandler.error((SAXParseException)(exceptions.elementAt(i))); } } // OK, finally report the event. if (namespaces) { String[] parts = processName(name.name, false, false); contentHandler.startElement(parts[0], parts[1], parts[2], attTmp); } else { contentHandler.startElement("", "", name.name, attTmp); } // Clear temporaries only when necessary because this may be // expensive and a doc may have lots of elements w/o attributes if (haveAttributes) { attTmp.clear(); if (supportValidation && isValidating && namespaces && !prefixes) { nsAttTmp.removeAllElements(); } } // prepare to validate the content of this element. // in nonvalidating parsers, this accepts ANY content validator = newValidator (element); if (hasContent) { content (element, false, validator); // [42] ETag ::= '</' Name S? '>' // ... content swallowed "</" if (!in.peek (name.name, name.chars)) fatal ("P-034", new Object [] { name.name, new Integer (startLine) }); in.maybeWhitespace (); } nextChar ('>', "F-027", name.name); validator.done (); if (namespaces) { // Split the name. Unfortunately, we can't always reuse the // info from the startElement event above b/c this element may // have subelements and a global temporary is used. String[] parts = processName(name.name, false, false); // Report appropriate events... contentHandler.endElement(parts[0], parts[1], parts[2]); Enumeration prefixes = nsSupport.getDeclaredPrefixes(); while (prefixes.hasMoreElements()) { String prefix = (String)prefixes.nextElement(); contentHandler.endPrefixMapping(prefix); } nsSupport.popContext(); } else { contentHandler.endElement("", "", name.name); } return true; } /** * Process attributes for namespace support. This is mostly common * code that gets called from two places and was factored out. The * <code>isDefaulting</code> param specifies where the code is called * from. * * @param isDefaulting true iff we are processing this attribute from * the <code>defaultAttributes(...)</code> method * * The namespace processing code is derived from the SAX2 ParserAdapter * code. This code should be kept in sync with ParserAdapter bug * fixes. * * Note: Modifies <code>seenNSDecl</code> iff a xmlns attribute, ie a * namespace decl, was found. Modifies <code>attTmp</code> and * <code>nsAttTmp</code>. */ private Vector processAttributeNS(String attQName, String type, String value, String defaultValue, boolean isSpecified, boolean isDefaulting, Vector exceptions) throws SAXException { // assert(namespaces == true) nonNamespace: if (attQName.startsWith("xmlns")) { // Could be a namespace declaration boolean defaultNSDecl = attQName.length() == 5; if (!defaultNSDecl && attQName.charAt(5) != ':') { // Not a namespace declaration break nonNamespace; } // Must be some kind of namespace declaration String prefix; if (defaultNSDecl) { // Default namespace, so use empty string as prefix prefix = ""; } else { // Non-default namespace decl, extract the prefix prefix = attQName.substring(6); } if (!nsSupport.declarePrefix(prefix, value)) { error("P-083", new Object[] { prefix }); } contentHandler.startPrefixMapping(prefix, value); // We may need to add this attribute to appropriate lists if (prefixes) { attTmp.addAttribute("", prefix, attQName.intern(), type, value, defaultValue, isSpecified); } else if (supportValidation && isValidating && !isDefaulting) { // Add this namespace attribute to a different list that // will be used to check for #REQUIRED attributes later. // Since "prefixes" is false, these are not reported to the // ContentHandler. This step is not needed during the // second pass of attribute processing where default values // are provided. nsAttTmp.addElement(attQName); } seenNSDecl = true; return exceptions; } // This isn't a namespace declaration. try { String attName[] = processName(attQName, true, true); attTmp.addAttribute(attName[0], attName[1], attName[2], type, value, defaultValue, isSpecified); } catch (SAXException e) { if (exceptions == null) { exceptions = new Vector(); } exceptions.addElement(e); attTmp.addAttribute("", attQName, attQName, type, value, defaultValue, isSpecified); } return exceptions; } /** * Process a qualified (prefixed) name. * * <p>If the name has an undeclared prefix, use only the qname * and make an ErrorHandler.error callback in case the app is * interested.</p> * * @param qName The qualified (prefixed) name. * @param isAttribute true if this is an attribute name. * @return The name split into three parts. * @exception org.xml.sax.SAXException The client may throw * an exception if there is an error callback. */ private String[] processName(String qName, boolean isAttribute, boolean useException) throws SAXException { // assert(namespaces == true) String parts[] = nsSupport.processName(qN
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?