private void SetIdenticalAttribute(bool remove) { if (ownerElement == null) { return; } // Check if new attribute's datatype is ID. XmlDocumentType doctype = ownerDocument.DocumentType; if (doctype == null || doctype.DTD == null) { return; } DTDElementDeclaration elem = doctype.DTD.ElementDecls [ownerElement.Name]; for (int i = 0; i < Count; i++) { XmlAttribute node = (XmlAttribute)Nodes [i]; DTDAttributeDefinition attdef = elem == null ? null : elem.Attributes [node.Name]; if (attdef == null || attdef.Datatype.TokenizedType != XmlTokenizedType.ID) { continue; } if (remove) { if (ownerDocument.GetIdenticalAttribute(node.Value) != null) { ownerDocument.RemoveIdenticalAttribute(node.Value); return; } } else { // adding new identical attribute, but // MS.NET is pity for ID support, so I'm wondering how to correct it... if (ownerDocument.GetIdenticalAttribute(node.Value) != null) { throw new XmlException(String.Format( "ID value {0} already exists in this document.", node.Value)); } ownerDocument.AddIdenticalAttribute(node); return; } } }
private void SetIdenticalAttribute(bool remove) { if (this.ownerElement == null) { return; } XmlDocumentType documentType = this.ownerDocument.DocumentType; if (documentType == null || documentType.DTD == null) { return; } DTDElementDeclaration dtdelementDeclaration = documentType.DTD.ElementDecls[this.ownerElement.Name]; for (int i = 0; i < this.Count; i++) { XmlAttribute xmlAttribute = (XmlAttribute)base.Nodes[i]; DTDAttributeDefinition dtdattributeDefinition = (dtdelementDeclaration != null) ? dtdelementDeclaration.Attributes[xmlAttribute.Name] : null; if (dtdattributeDefinition != null && dtdattributeDefinition.Datatype.TokenizedType == XmlTokenizedType.ID) { if (remove) { if (this.ownerDocument.GetIdenticalAttribute(xmlAttribute.Value) != null) { this.ownerDocument.RemoveIdenticalAttribute(xmlAttribute.Value); return; } } else { if (this.ownerDocument.GetIdenticalAttribute(xmlAttribute.Value) != null) { throw new XmlException(string.Format("ID value {0} already exists in this document.", xmlAttribute.Value)); } this.ownerDocument.AddIdenticalAttribute(xmlAttribute); return; } } } }
// Read 'cp' (BNF) of contentdecl (BNF) private DTDContentModel ReadCP (DTDElementDeclaration elem) { DTDContentModel model = null; TryExpandPERef (); if(PeekChar () == '(') { model = new DTDContentModel (DTD, elem.Name); ReadChar (); SkipWhitespace (); model.ChildModels.Add (ReadCP (elem)); SkipWhitespace (); do { if (PeekChar () == '%') { TryExpandPERef (); continue; } if(PeekChar ()=='|') { // CPType=Or if (model.OrderType == DTDContentOrderType.Seq) throw NotWFError ("Inconsistent choice markup in sequence cp."); model.OrderType = DTDContentOrderType.Or; ReadChar (); SkipWhitespace (); AddContentModel (model.ChildModels, ReadCP (elem)); SkipWhitespace (); } else if(PeekChar () == ',') { // CPType=Seq if (model.OrderType == DTDContentOrderType.Or) throw NotWFError ("Inconsistent sequence markup in choice cp."); model.OrderType = DTDContentOrderType.Seq; ReadChar (); SkipWhitespace (); model.ChildModels.Add (ReadCP (elem)); SkipWhitespace (); } else break; } while(true); ExpectAfterWhitespace (')'); } else { TryExpandPERef (); model = new DTDContentModel (DTD, elem.Name); model.ElementName = ReadName (); } switch(PeekChar ()) { case '?': model.Occurence = DTDOccurence.Optional; ReadChar (); break; case '*': model.Occurence = DTDOccurence.ZeroOrMore; ReadChar (); break; case '+': model.Occurence = DTDOccurence.OneOrMore; ReadChar (); break; } return model; }
// read 'children'(BNF) of contentspec private void ReadContentSpec (DTDElementDeclaration decl) { TryExpandPERef (); switch(ReadChar ()) { case 'E': decl.IsEmpty = true; Expect ("MPTY"); break; case 'A': decl.IsAny = true; Expect ("NY"); break; case '(': DTDContentModel model = decl.ContentModel; SkipWhitespace (); TryExpandPERef (); if(PeekChar () == '#') { // Mixed Contents. "#PCDATA" must appear first. decl.IsMixedContent = true; model.Occurence = DTDOccurence.ZeroOrMore; model.OrderType = DTDContentOrderType.Or; Expect ("#PCDATA"); SkipWhitespace (); TryExpandPERef (); while(PeekChar () != ')') { SkipWhitespace (); if (PeekChar () == '%') { TryExpandPERef (); continue; } Expect('|'); SkipWhitespace (); TryExpandPERef (); DTDContentModel elem = new DTDContentModel (DTD, decl.Name); // elem.LineNumber = currentInput.LineNumber; // elem.LinePosition = currentInput.LinePosition; elem.ElementName = ReadName (); this.AddContentModel (model.ChildModels, elem); SkipWhitespace (); TryExpandPERef (); } Expect (')'); if (model.ChildModels.Count > 0) Expect ('*'); else if (PeekChar () == '*') Expect ('*'); } else { // Non-Mixed Contents model.ChildModels.Add (ReadCP (decl)); SkipWhitespace (); do { // copied from ReadCP() ...;-) if (PeekChar () == '%') { TryExpandPERef (); continue; } if(PeekChar ()=='|') { // CPType=Or if (model.OrderType == DTDContentOrderType.Seq) throw NotWFError ("Inconsistent choice markup in sequence cp."); model.OrderType = DTDContentOrderType.Or; ReadChar (); SkipWhitespace (); AddContentModel (model.ChildModels, ReadCP (decl)); SkipWhitespace (); } else if(PeekChar () == ',') { // CPType=Seq if (model.OrderType == DTDContentOrderType.Or) throw NotWFError ("Inconsistent sequence markup in choice cp."); model.OrderType = DTDContentOrderType.Seq; ReadChar (); SkipWhitespace (); model.ChildModels.Add (ReadCP (decl)); SkipWhitespace (); } else break; } while(true); Expect (')'); switch(PeekChar ()) { case '?': model.Occurence = DTDOccurence.Optional; ReadChar (); break; case '*': model.Occurence = DTDOccurence.ZeroOrMore; ReadChar (); break; case '+': model.Occurence = DTDOccurence.OneOrMore; ReadChar (); break; } SkipWhitespace (); } SkipWhitespace (); break; default: throw NotWFError ("ContentSpec is missing."); } }
// The reader is positioned on the head of the name. private DTDElementDeclaration ReadElementDecl () { DTDElementDeclaration decl = new DTDElementDeclaration (DTD); decl.IsInternalSubset = this.processingInternalSubset; if (!SkipWhitespace ()) throw NotWFError ("Whitespace is required between '<!ELEMENT' and name in DTD element declaration."); TryExpandPERef (); decl.Name = ReadName (); if (!SkipWhitespace ()) throw NotWFError ("Whitespace is required between name and content in DTD element declaration."); TryExpandPERef (); ReadContentSpec (decl); SkipWhitespace (); // This expanding is only allowed as a non-validating parser. TryExpandPERef (); Expect ('>'); return decl; }