📄 xmlparser.java
字号:
skipWhitespace(); } } else if (tryRead("IGNORE")) { skipWhitespace(); require('['); expandPE = false; for (int nesting = 1; nesting > 0; ) { int c = readCh(); switch (c) { case 0x3c: // '<' if (tryRead("![")) nesting++; break; case 0x5d: // ']' if (tryRead("]>")) nesting--; break; case -1: throw new EOFException(); } } expandPE = saved; } else error("conditional section must begin with INCLUDE or IGNORE"); } else error("expected markup declaration"); } /** * Parse the elementdecl production. */ private void readElementDecl() throws IOException, XMLStreamException { requireWhitespace(); boolean saved = expandPE; expandPE = (inputStack.size() > 1); String name = readNmtoken(true); expandPE = saved; requireWhitespace(); readContentspec(name); skipWhitespace(); require('>'); } /** * Parse the contentspec production. */ private void readContentspec(String elementName) throws IOException, XMLStreamException { if (tryRead("EMPTY")) doctype.addElementDecl(elementName, "EMPTY", new EmptyContentModel()); else if (tryRead("ANY")) doctype.addElementDecl(elementName, "ANY", new AnyContentModel()); else { ContentModel model; StringBuffer acc = new StringBuffer(); require('('); acc.append('('); skipWhitespace(); if (tryRead("#PCDATA")) { // mixed content acc.append("#PCDATA"); MixedContentModel mm = new MixedContentModel(); model = mm; skipWhitespace(); if (tryRead(')')) { acc.append(")"); if (tryRead('*')) { mm.min = 0; mm.max = -1; } } else { while (!tryRead(")")) { require('|'); acc.append('|'); skipWhitespace(); String name = readNmtoken(true); acc.append(name); mm.addName(name); skipWhitespace(); } require('*'); acc.append(")*"); mm.min = 0; mm.max = -1; } } else model = readElements(acc); doctype.addElementDecl(elementName, acc.toString(), model); } } /** * Parses an element content model. */ private ElementContentModel readElements(StringBuffer acc) throws IOException, XMLStreamException { int separator; ElementContentModel model = new ElementContentModel(); // Parse first content particle skipWhitespace(); model.addContentParticle(readContentParticle(acc)); // End or separator skipWhitespace(); int c = readCh(); switch (c) { case 0x29: // ')' acc.append(')'); mark(1); c = readCh(); switch (c) { case 0x3f: // '?' acc.append('?'); model.min = 0; model.max = 1; break; case 0x2a: // '*' acc.append('*'); model.min = 0; model.max = -1; break; case 0x2b: // '+' acc.append('+'); model.min = 1; model.max = -1; break; default: reset(); } return model; // done case 0x7c: // '|' model.or = true; // fall through case 0x2c: // ',' separator = c; acc.append(Character.toChars(c)); break; default: error("bad separator in content model", "U+" + Integer.toHexString(c)); return model; } // Parse subsequent content particles while (true) { skipWhitespace(); model.addContentParticle(readContentParticle(acc)); skipWhitespace(); c = readCh(); if (c == 0x29) // ')' { acc.append(')'); break; } else if (c != separator) { error("bad separator in content model", "U+" + Integer.toHexString(c)); return model; } else acc.append(c); } // Check for occurrence indicator mark(1); c = readCh(); switch (c) { case 0x3f: // '?' acc.append('?'); model.min = 0; model.max = 1; break; case 0x2a: // '*' acc.append('*'); model.min = 0; model.max = -1; break; case 0x2b: // '+' acc.append('+'); model.min = 1; model.max = -1; break; default: reset(); } return model; } /** * Parse a cp production. */ private ContentParticle readContentParticle(StringBuffer acc) throws IOException, XMLStreamException { ContentParticle cp = new ContentParticle(); if (tryRead('(')) { acc.append('('); cp.content = readElements(acc); } else { String name = readNmtoken(true); acc.append(name); cp.content = name; mark(1); int c = readCh(); switch (c) { case 0x3f: // '?' acc.append('?'); cp.min = 0; cp.max = 1; break; case 0x2a: // '*' acc.append('*'); cp.min = 0; cp.max = -1; break; case 0x2b: // '+' acc.append('+'); cp.min = 1; cp.max = -1; break; default: reset(); } } return cp; } /** * Parse an attribute-list definition. */ private void readAttlistDecl() throws IOException, XMLStreamException { requireWhitespace(); boolean saved = expandPE; expandPE = (inputStack.size() > 1); String elementName = readNmtoken(true); expandPE = saved; boolean white = tryWhitespace(); while (!tryRead('>')) { if (!white) error("whitespace required before attribute definition"); readAttDef(elementName); white = tryWhitespace(); } } /** * Parse a single attribute definition. */ private void readAttDef(String elementName) throws IOException, XMLStreamException { String name = readNmtoken(true); requireWhitespace(); StringBuffer acc = new StringBuffer(); HashSet values = new HashSet(); String type = readAttType(acc, values); if (validating) { if ("ID".equals(type)) { // VC: One ID per Element Type for (Iterator i = doctype.attlistIterator(elementName); i.hasNext(); ) { Map.Entry entry = (Map.Entry) i.next(); AttributeDecl decl = (AttributeDecl) entry.getValue(); if ("ID".equals(decl.type)) error("element types must not have more than one ID " + "attribute"); } } else if ("NOTATION".equals(type)) { // VC: One Notation Per Element Type for (Iterator i = doctype.attlistIterator(elementName); i.hasNext(); ) { Map.Entry entry = (Map.Entry) i.next(); AttributeDecl decl = (AttributeDecl) entry.getValue(); if ("NOTATION".equals(decl.type)) error("element types must not have more than one NOTATION " + "attribute"); } // VC: No Notation on Empty Element ContentModel model = doctype.getElementModel(elementName); if (model != null && model.type == ContentModel.EMPTY) error("attributes of type NOTATION must not be declared on an " + "element declared EMPTY"); } } String enumer = null; if ("ENUMERATION".equals(type) || "NOTATION".equals(type)) enumer = acc.toString(); else values = null; requireWhitespace(); readDefault(elementName, name, type, enumer, values); } /** * Parse an attribute type. */ private String readAttType(StringBuffer acc, HashSet values) throws IOException, XMLStreamException { if (tryRead('(')) { readEnumeration(false, acc, values); return "ENUMERATION"; } else { String typeString = readNmtoken(true); if ("NOTATION".equals(typeString)) { readNotationType(acc, values); return typeString; } else if ("CDATA".equals(typeString) || "ID".equals(typeString) || "IDREF".equals(typeString) || "IDREFS".equals(typeString) || "ENTITY".equals(typeString) || "ENTITIES".equals(typeString) || "NMTOKEN".equals(typeString) || "NMTOKENS".equals(typeString)) return typeString; else { error("illegal attribute type", typeString); return null; } } } /** * Parse an enumeration. */ private void readEnumeration(boolean isNames, StringBuffer acc, HashSet values) throws IOException, XMLStreamException { acc.append('('); // first token skipWhitespace(); String token = readNmtoken(isNames); acc.append(token); values.add(token); // subsequent tokens skipWhitespace(); while (!tryRead(')')) { require('|'); acc.append('|'); skipWhitespace(); token = readNmtoken(isNames); // VC: No Duplicate Tokens if (validating && values.contains(token)) error("duplicate token", token); acc.append(token); values.add(token); skipWhitespace(); } acc.append(')'); } /** * Parse a notation type for an attribute. */ private void readNotationType(StringBuffer acc, HashSet values) throws IOException, XMLStreamException { requireWhitespace(); require('('); readEnumeration(true, acc, values); } /** * Parse the default value for an attribute. */ private void readDefault(String elementName, String name, String type, String enumeration, HashSet values) throws IOException, XMLStreamException { int valueType = ATTRIBUTE_DEFAULT_SPECIFIED; int flags = LIT_ATTRIBUTE; String value = null, defaultType = null; boolean saved = expandPE; if (!"CDATA".equals(type)) flags |= LIT_NORMALIZE; expandPE = false; if (tryRead('#')) { if (tryRead("FIXED")) { defaultType = "#FIXED"; valueType = ATTRIBUTE_DEFAULT_FIXED; requireWhitespace(); value = readLiteral(flags, false); } else if (tryRead("REQUIRED")) { defaultType = "#REQUIRED"; valueType = ATTRIBUTE_DEFAULT_REQUIRED; } else if (tryRead("IMPLIED")) { defaultType = "#IMPLIED"; valueType = ATTRIBUTE_DEFAULT_IMPLIED; } else error("illegal keyword for attribute default value"); } else value = readLiteral(flags, false); expandPE = saved; if (validating) { if ("ID".equals(type)) { // VC: Attribute Default Value Syntactically Correct if (value != null && !isNmtoken(value, true)) error("default value must match Name production", value); // VC: ID Attribute Default if (valueType != ATTRIBUTE_DEFAULT_REQUIRED && valueType != ATTRIBUTE_DEFAULT_IMPLIED) error("ID attributes must have a declared default of " + "#IMPLIED or #REQUIRED"); } else if (value != null) { // VC: Attribute Default Value Syntacti
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -