📄 dtdparser.java
字号:
} protected DTDContainer parseChoiceSequence() throws IOException { TokenType separator = null; DTDContainer cs = null; for (;;) { DTDItem item = parseCP(); Token token = scanner.get(); if ((token.type == Scanner.PIPE) || (token.type == Scanner.COMMA)) { if ((separator != null) && (separator != token.type)) { throw new DTDParseException(scanner.getUriId(), "Can't mix separators in a choice/sequence", scanner.getLineNumber(), scanner.getColumn()); } separator = token.type; if (cs == null) { if (token.type == Scanner.PIPE) { cs = new DTDChoice(); } else { cs = new DTDSequence(); } } cs.add(item); } else if (token.type == Scanner.RPAREN) { if (cs == null) { cs = new DTDSequence(); } cs.add(item); return cs; } else { throw new DTDParseException(scanner.getUriId(), "Found invalid token in sequence: "+ token.type.name, scanner.getLineNumber(), scanner.getColumn()); } } } protected DTDItem parseCP() throws IOException { Token token = scanner.get(); DTDItem item = null; if (token.type == Scanner.IDENTIFIER) { item = new DTDName(token.value); } else if (token.type == Scanner.LPAREN) { item = parseChoiceSequence(); } else { throw new DTDParseException(scanner.getUriId(), "Found invalid token in sequence: "+ token.type.name, scanner.getLineNumber(), scanner.getColumn()); } item.cardinal = parseCardinality(); return item; } protected DTDCardinal parseCardinality() throws IOException { Token token = scanner.peek(); if (token.type == Scanner.QUES) { scanner.get(); return DTDCardinal.OPTIONAL; } else if (token.type == Scanner.ASTERISK) { scanner.get(); return DTDCardinal.ZEROMANY; } else if (token.type == Scanner.PLUS) { scanner.get(); return DTDCardinal.ONEMANY; } else { return DTDCardinal.NONE; } } protected void parseAttlist() throws IOException { Token token = expect(Scanner.IDENTIFIER); DTDElement element = (DTDElement) dtd.elements.get(token.value); DTDAttlist attlist = new DTDAttlist(token.value); dtd.items.addElement(attlist); if (element == null) { element = new DTDElement(token.value); dtd.elements.put(token.value, element); } token = scanner.peek(); while (token.type != Scanner.GT) { parseAttdef(scanner, element, attlist); token = scanner.peek(); }// MAW Version 1.17// Prior to this version, the parser didn't actually consume the > at the// end of the ATTLIST definition. Because the parser ignored unexpected tokens// at the top level, it was ignoring the >. In parsing DOCBOOK, however, there// were two unexpected tokens, bringing this error to light. expect(Scanner.GT); } protected void parseAttdef(Scanner scanner, DTDElement element, DTDAttlist attlist) throws IOException { Token token = expect(Scanner.IDENTIFIER); DTDAttribute attr = new DTDAttribute(token.value); attlist.attributes.addElement(attr); element.attributes.put(token.value, attr); token = scanner.get(); if (token.type == Scanner.IDENTIFIER) { if (token.value.equals("NOTATION")) { attr.type = parseNotationList(); } else { attr.type = token.value; } } else if (token.type == Scanner.LPAREN) { attr.type = parseEnumeration(); } token = scanner.peek(); if (token.type == Scanner.IDENTIFIER) { scanner.get(); if (token.value.equals("#FIXED")) { attr.decl = DTDDecl.FIXED; token = scanner.get(); attr.defaultValue = token.value; } else if (token.value.equals("#REQUIRED")) { attr.decl = DTDDecl.REQUIRED; } else if (token.value.equals("#IMPLIED")) { attr.decl = DTDDecl.IMPLIED; } else { throw new DTDParseException(scanner.getUriId(), "Invalid token in attribute declaration: "+ token.value, scanner.getLineNumber(), scanner.getColumn()); } } else if (token.type == Scanner.STRING) { scanner.get(); attr.decl = DTDDecl.VALUE; attr.defaultValue = token.value; } } protected DTDNotationList parseNotationList() throws IOException { DTDNotationList notation = new DTDNotationList(); Token token = scanner.get(); if (token.type != Scanner.LPAREN) { throw new DTDParseException(scanner.getUriId(), "Invalid token in notation: "+ token.type.name, scanner.getLineNumber(), scanner.getColumn()); } for (;;) { token = scanner.get(); if (token.type != Scanner.IDENTIFIER) { throw new DTDParseException(scanner.getUriId(), "Invalid token in notation: "+ token.type.name, scanner.getLineNumber(), scanner.getColumn()); } notation.add(token.value); token = scanner.peek(); if (token.type == Scanner.RPAREN) { scanner.get(); return notation; } else if (token.type != Scanner.PIPE) { throw new DTDParseException(scanner.getUriId(), "Invalid token in notation: "+ token.type.name, scanner.getLineNumber(), scanner.getColumn()); } scanner.get(); // eat the pipe } } protected DTDEnumeration parseEnumeration() throws IOException { DTDEnumeration enumeration = new DTDEnumeration(); for (;;) { Token token = scanner.get(); if ((token.type != Scanner.IDENTIFIER) && (token.type != Scanner.NMTOKEN)) { throw new DTDParseException(scanner.getUriId(), "Invalid token in enumeration: "+ token.type.name, scanner.getLineNumber(), scanner.getColumn()); } enumeration.add(token.value); token = scanner.peek(); if (token.type == Scanner.RPAREN) { scanner.get(); return enumeration; } else if (token.type != Scanner.PIPE) { throw new DTDParseException(scanner.getUriId(), "Invalid token in enumeration: "+ token.type.name, scanner.getLineNumber(), scanner.getColumn()); } scanner.get(); // eat the pipe } } protected void parseEntity() throws IOException { boolean isParsed = false; Token name = scanner.get(); if (name.type == Scanner.PERCENT) { isParsed = true; name = expect(Scanner.IDENTIFIER); } else if (name.type != Scanner.IDENTIFIER) { throw new DTDParseException(scanner.getUriId(), "Invalid entity declaration", scanner.getLineNumber(), scanner.getColumn()); } DTDEntity entity = (DTDEntity) dtd.entities.get(name.value); boolean skip = false; if (entity == null) { entity = new DTDEntity(name.value, defaultLocation); dtd.entities.put(entity.name, entity); } else {// 070501 MAW: If the entity already exists, create a dummy entity - this way// you keep the original definition. Thanks to Jags Krishnamurthy of Object// Edge for pointing out this problem and for pointing out the solution entity = new DTDEntity(name.value, defaultLocation); skip = true; } dtd.items.addElement(entity); entity.isParsed = isParsed; parseEntityDef(entity); if (entity.isParsed && (entity.value != null) && !skip) { scanner.addEntity(entity.name, entity.value); } } protected void parseEntityDef(DTDEntity entity) throws IOException { Token token = scanner.get(); if (token.type == Scanner.STRING) { // Only set the entity value if it hasn't been set yet // XML 1.0 spec says that you use the first value of // an entity, not the most recent. if (entity.value == null) { entity.value = token.value; } } else if (token.type == Scanner.IDENTIFIER) { if (token.value.equals("SYSTEM")) { DTDSystem sys = new DTDSystem(); token = expect(Scanner.STRING); sys.system = token.value; entity.externalID = sys; } else if (token.value.equals("PUBLIC")) { DTDPublic pub = new DTDPublic(); token = expect(Scanner.STRING); pub.pub = token.value; token = expect(Scanner.STRING); pub.system = token.value; entity.externalID = pub; } else { throw new DTDParseException(scanner.getUriId(), "Invalid External ID specification", scanner.getLineNumber(), scanner.getColumn()); } // ISSUE: isParsed is set to TRUE if this is a Parameter Entity // Reference (assuming this is because Parameter Entity // external references are parsed, whereas General Entity // external references are irrelevant for this product). // However, NDATA is only valid if this is // a General Entity Reference. So, "if" conditional should // be (!entity.isParsed) rather than (entity.isParsed). // //Entity Declaration // [70] EntityDecl ::= GEDecl | PEDecl // [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>' // [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>' // [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?) // [74] PEDef ::= EntityValue | ExternalID //External Entity Declaration // [75] ExternalID ::= 'SYSTEM' S SystemLiteral // | 'PUBLIC' S PubidLiteral S SystemLiteral // [76] NDataDecl ::= S 'NDATA' S Name [ VC: Notation Declared ] if (!entity.isParsed) // CHANGE 1 { token = scanner.peek(); if (token.type == Scanner.IDENTIFIER) { if (!token.value.equals("NDATA")) { throw new DTDParseException(scanner.getUriId(), "Invalid NData declaration", scanner.getLineNumber(), scanner.getColumn()); } // CHANGE 2: Add call to scanner.get. // This gets "NDATA" IDENTIFIER. token = scanner.get(); // Get the NDATA "Name" IDENTIFIER. token = expect(Scanner.IDENTIFIER); // Save the ndata value entity.ndata = token.value; } } } else { throw new DTDParseException(scanner.getUriId(), "Invalid entity definition", scanner.getLineNumber(), scanner.getColumn()); } expect(Scanner.GT); } protected void parseNotation() throws java.io.IOException { DTDNotation notation = new DTDNotation(); Token token = expect(Scanner.IDENTIFIER); notation.name = token.value; dtd.notations.put(notation.name, notation); dtd.items.addElement(notation); token = expect(Scanner.IDENTIFIER); if (token.value.equals("SYSTEM")) { DTDSystem sys = new DTDSystem(); token = expect(Scanner.STRING); sys.system = token.value; notation.externalID = sys; } else if (token.value.equals("PUBLIC")) { DTDPublic pub = new DTDPublic(); token = expect(Scanner.STRING); pub.pub = token.value; pub.system = null;// For <!NOTATION>, you can have PUBLIC PubidLiteral without// a SystemLiteral token = scanner.peek(); if (token.type == Scanner.STRING) { token = scanner.get(); pub.system = token.value; } notation.externalID = pub; } expect(Scanner.GT); } public DTDEntity expandEntity(String name) { return (DTDEntity) dtd.entities.get(name); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -