dtdparser.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,072 行 · 第 1/2 页
JAVA
1,072 行
return parseContentParticle(cp, true); } } /** * Parses a content-particle, i.e. a grammer particle in the DTD * regexp. */ private int parseContentParticle(QContentParticle cp, boolean isTop) throws IOException, SAXException { boolean hasCdata = false; cp._separator = 0; cp._repeat = 0; int ch; ch = expandPE(read()); for (; ch != -1; ch = expandPE(ch)) { if (ch == '(') { QContentParticle child = new QContentParticle(); cp.addChild(child); ch = parseContentParticle(child, false); } else if (XmlChar.isNameStart(ch)) { ch = _xmlParser.parseName(_text, ch); cp.addChild(_text.toString()); } else if (ch == '#') { ch = _xmlParser.parseName(_text, read()); String name = _text.toString(); if (cp._children.size() != 0) throw error(L.l("'#{0}' must occur first", name)); if (! isTop) throw error(L.l("'#{0}' may only occur at top level", name)); if (name.equals("PCDATA")) cp.addChild("#PCDATA"); else throw error(L.l("illegal content particle at '#{0}'", name)); hasCdata = true; } else throw error(L.l("expected content particle at {0}", badChar(ch))); ch = expandPE(ch); if (ch == '?' || ch == '*' || ch == '+') { Object child = cp.getChild(cp.getChildSize() - 1); if (child instanceof QContentParticle) { QContentParticle cpChild = (QContentParticle) child; cpChild._repeat = ch; } else { QContentParticle cpChild = new QContentParticle(); cpChild.addChild(child); cpChild._repeat = ch; cp.setChild(cp.getChildSize() - 1, cpChild); } ch = expandPE(read()); } if (ch == ')') break; else if (cp._separator == 0) { if (ch == '|') cp._separator = ch; else if (hasCdata) throw error(L.l("#PCDATA must be separated by '|' at {0}", badChar(ch))); else if (ch == ',') cp._separator = ch; else throw error(L.l("expected separator at {0}", badChar(ch))); ch = read(); } else if (ch != cp._separator) throw error(L.l("expected '{0}' at {1}", "" + (char) cp._separator, badChar(ch))); else ch = read(); } ch = expandPE(read()); if (hasCdata && (ch == '+' || ch == '?')) throw error(L.l("pcdata clause can not have {0}", badChar(ch))); else if (ch == '*' || ch == '+' || ch == '?') { cp._repeat = ch; return read(); } else return ch; } private int expandPE(int ch) throws IOException, SAXException { ch = _xmlParser.skipWhitespace(ch); while (ch == '%') { parsePEReference(); ch = _xmlParser.skipWhitespace(read()); } return ch; } /** * Parses a PE reference %foo; and inserts the macro text to the input * stream. */ private void parsePEReference() throws IOException, SAXException { int ch = _xmlParser.parseName(_buf, read()); if (ch != ';') throw error(L.l("'%{0};' expects ';' at {1}. Parameter entities have a '%name;' syntax.", _buf, badChar(ch))); addPEReference(_text, _buf.toString()); } /** * Expands the macro value of a PE reference. */ private void addPEReference(CharBuffer value, String name) throws IOException, SAXException { QEntity entity = _dtd.getParameterEntity(name); if (entity == null && ! _dtd.isExternal()) throw error(L.l("'%{0};' is an unknown parameter entity. Parameter entities must be defined in an <!ENTITY> declaration before use.", name)); else if (entity != null && entity._value != null) { _xmlParser.setMacro(entity._value); } else if (entity != null && entity.getSystemId() != null) { _xmlParser.pushInclude(entity.getPublicId(), entity.getSystemId()); } else { value.append("%"); value.append(name); value.append(";"); } } /** * <!ELEMENT name contentspec> */ private void parseElementDecl(QDocumentType doctype) throws IOException, SAXException { int ch = _xmlParser.skipWhitespace(read()); ch = _xmlParser.parseName(_text, ch); String name = _text.toString(); ch = _xmlParser.skipWhitespace(ch); QElementDef def = _dtd.addElement(name); def.setLocation(getSystemId(), getFilename(), getLine(), getColumn()); boolean needsStartTag = true; boolean needsEndTag = true; ch = parseContentSpec(def, ch); ch = _xmlParser.skipWhitespace(ch); if (ch != '>') throw error(L.l("'<!ELEMENT' must close with '>' at {0}", badChar(ch))); } private static String toAttrDefault(CharBuffer text) { for (int i = 0; i < text.length(); i++) { int ch = text.charAt(i); if (ch == '"') { text.delete(i, i + 1); text.insert(i, """); i--; } else if (ch == '\'') { text.delete(i, i + 1); text.insert(i, "'"); i--; } } return text.toString(); } /** * <!ATTLIST name (attr type def)*> */ private void parseAttlistDecl(QDocumentType doctype) throws IOException, SAXException { int ch = _xmlParser.skipWhitespace(read()); ch = _xmlParser.parseName(_text, ch); String name = _text.toString(); ch = _xmlParser.skipWhitespace(ch); QElementDef def = _dtd.addElement(name); while (XmlChar.isNameStart((ch = expandPE(ch)))) { ch = _xmlParser.parseName(_text, ch); String attrName = _text.toString(); String attrType = null; ArrayList<String> enumeration = null; ch = expandPE(ch); if (ch == '(') { attrType = "#ENUM"; enumeration = new ArrayList<String>(); do { ch = expandPE(read()); ch = parseNameToken(_text, ch); enumeration.add(_text.toString()); ch = expandPE(ch); } while (ch == '|'); if (ch != ')') throw error(L.l("expected '{0}' at {1}. <!ATTRLIST> enumerations definitions are enclosed in '(' ... ')'.", ")", badChar(ch))); ch = read(); } else { ch = _xmlParser.parseName(_text, ch); attrType = _text.toString(); if (attrType.equals("NOTATION")) { enumeration = new ArrayList<String>(); ch = expandPE(ch); if (ch != '(') throw error(L.l("expected '{0}' at {1}", "(", badChar(ch))); do { ch = expandPE(read()); ch = _xmlParser.parseName(_text, ch); enumeration.add(_text.toString()); ch = expandPE(ch); } while (ch == '|'); if (ch != ')') throw error(L.l("expected '{0}' at {1}", ")", badChar(ch))); ch = read(); } else if (_attrTypes.get(attrType) != null) { } else throw error(L.l("expected attribute type at '{0}'", attrType)); } ch = _xmlParser.skipWhitespace(ch); String qualifier = null; String attrDefault = null; if (ch == '#') { ch = _xmlParser.parseName(_text, read()); qualifier = "#" + _text.toString(); if (qualifier.equals("#IMPLIED")) { } else if (qualifier.equals("#REQUIRED")) { } else if (qualifier.equals("#FIXED")) { ch = _xmlParser.skipWhitespace(ch); ch = parseValue(_text, ch, false); attrDefault = _text.toString(); } else throw error(L.l("expected attribute default at '{0}'", qualifier)); } else if (ch != '>') { ch = parseValue(_text, ch, false); attrDefault = _text.toString(); } def.addAttribute(attrName, attrType, enumeration, qualifier, attrDefault); if (attrType != null && attrType.equals("ID")) doctype.setElementId(name, attrName); ch = _xmlParser.skipWhitespace(ch); } if (ch != '>') throw error(L.l("expected '{0}' at {1}", ">", badChar(ch))); } /** * <!NOTATION name systemId publicId> */ private void parseNotationDecl(QDocumentType doctype) throws IOException, SAXException { int ch = _xmlParser.skipWhitespace(read()); ch = _xmlParser.parseName(_text, ch); String name = _text.toString(); ch = _xmlParser.skipWhitespace(ch); ch = _xmlParser.parseName(_text, ch); String key = _text.toString(); ch = _xmlParser.skipWhitespace(ch); ch = parseValue(_text, ch, false); String id = _text.toString(); ch = _xmlParser.skipWhitespace(ch); QNotation notation; if (key.equals("PUBLIC")) { String systemId = null; if (ch == '"' || ch == '\'') { ch = parseValue(_text, ch, false); ch = _xmlParser.skipWhitespace(ch); systemId = _text.toString(); } notation = new QNotation(name, id, systemId); notation._owner = doctype._owner; notation.setLocation(getSystemId(), getFilename(), getLine(), getColumn()); } else if (key.equals("SYSTEM")) { notation = new QNotation(name, null, id); notation._owner = doctype._owner; notation.setLocation(getSystemId(), getFilename(), getLine(), getColumn()); } else throw error(L.l("expected PUBLIC or SYSTEM at '{0}'", key)); doctype.addNotation(notation); doctype.appendChild(notation); if (ch != '>') throw error(L.l("expected '{0}' at {1}", ">", badChar(ch))); } /** * externalID ::= PUBLIC publicId systemId * ::= SYSTEM systemId */ private int parseExternalID(int ch) throws IOException, SAXException { ch = _xmlParser.parseName(_text, ch); String key = _text.toString(); ch = _xmlParser.skipWhitespace(ch); _extSystemId = null; _extPublicId = null; if (key.equals("PUBLIC")) { ch = parseValue(_text, ch, false); _extPublicId = _text.toString(); ch = _xmlParser.skipWhitespace(ch); if (_extPublicId.indexOf('&') > 0) throw error(L.l("Illegal character '&' in PUBLIC identifier '{0}'", _extPublicId)); ch = parseValue(_text, ch, false); ch = _xmlParser.skipWhitespace(ch); _extSystemId = _text.toString(); } else if (key.equals("SYSTEM")) { ch = parseValue(_text, ch, false); _extSystemId = _text.toString(); } else throw error(L.l("expected PUBLIC or SYSTEM at '{0}'", key)); return ch; } /** * <!ENTITY name systemId publicId> */ private void parseEntityDecl(QDocumentType doctype) throws IOException, SAXException { int ch = _xmlParser.skipWhitespace(read()); boolean isPe = ch == '%'; if (isPe) ch = _xmlParser.skipWhitespace(read()); ch = _xmlParser.parseName(_text, ch); String name = _text.toString(); ch = _xmlParser.skipWhitespace(ch); QEntity entity; if (ch == '"' || ch == '\'') { ch = parseValue(_text, ch, false); entity = new QEntity(name, _text.toString(), null, null); entity._owner = doctype._owner; entity.setLocation(getSystemId(), getFilename(), getLine(), getColumn()); } else { ch = parseExternalID(ch); entity = new QEntity(name, null, _extPublicId, _extSystemId); entity._owner = doctype._owner; entity.setLocation(getSystemId(), getFilename(), getLine(), getColumn()); ch = _xmlParser.skipWhitespace(ch); if (! isPe && XmlChar.isNameStart(ch)) { ch = _xmlParser.parseName(_text, ch); String key = _text.toString(); if (key.equals("NDATA")) { ch = _xmlParser.skipWhitespace(ch); ch = _xmlParser.parseName(_text, ch); String ndata = _text.toString(); entity._ndata = ndata; } else throw error(L.l("expected 'NDATA' at '{0}'", key)); } } entity._isPe = isPe; if (isPe) doctype.addParameterEntity(entity); else doctype.addEntity(entity); doctype.appendChild(entity); ch = _xmlParser.skipWhitespace(ch); if (ch != '>') throw error(L.l("expected '>' at {0}", badChar(ch))); } private boolean isWhitespace(int ch) { return ch <= 0x20 && (ch == 0x20 || ch == 0x9 || ch == 0xa || ch == 0xd); } private boolean isChar(int ch) { return (ch >= 0x20 && ch <= 0xd7ff || ch == 0x9 || ch == 0xa || ch == 0xd || ch >= 0xe000 && ch <= 0xfffd); } /** * Returns the hex representation of a byte. */ private static String hex(int value) { CharBuffer cb = CharBuffer.allocate(); for (int b = 3; b >= 0; b--) { int v = (value >> (4 * b)) & 0xf; if (v < 10) cb.append((char) (v + '0')); else cb.append((char) (v - 10 + 'a')); } return cb.close(); } private int read() throws IOException, SAXException { return _xmlParser.read(); } public void unread(int ch) { _xmlParser.unread(ch); } private String getSystemId() { return _xmlParser.getSystemId(); } private String getFilename() { return _xmlParser.getFilename(); } private XmlParseException error(String msg) { return _xmlParser.error(msg); } private int getLine() { return _xmlParser.getLine(); } private int getColumn() { return _xmlParser.getColumn(); } private String badChar(int ch) { return _xmlParser.badChar(ch); } static { _attrTypes.put("CDATA", "CDATA"); _attrTypes.put("ID", "ID"); _attrTypes.put("IDREF", "IDREF"); _attrTypes.put("IDREFS", "IDREFS"); _attrTypes.put("ENTITY", "ENTITY"); _attrTypes.put("ENTITIES", "ENTITIES"); _attrTypes.put("NMTOKEN", "NMTOKEN"); _attrTypes.put("NMTOKENS", "NMTOKENS"); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?