/// <summary> /// Checks all test patterns for validity within the scope of the read DTD /// </summary> private void CheckAllTestPattern(List <DtdTestpattern> allPattern, XmlCursorPos cursorPos) { var node = cursorPos.ActualNode; DtdElement element_; if (cursorPos.PosOnNode == XmlCursorPositions.CursorInsideTheEmptyNode) { // Get the DTD element for the node of the cursor element_ = dtd.DTDElementByName(Dtd.GetElementNameFromNode(node), false); } else { if ((node.OwnerDocument == null) || (node.OwnerDocument.DocumentElement == null)) { Debug.Assert(false, "Beep!"); return; } else { if (node == node.OwnerDocument.DocumentElement) // The node is the root element { // Only the root element is allowed in place of the root element foreach (DtdTestpattern muster in allPattern) { if (muster.ElementName == node.Name) // if it is the root element { muster.Success = true; // Only the root element is allowed at the position of the root element } } return; } else // The node is not the root element { // Get the DTD element for the parent node of the cursor element_ = dtd.DTDElementByName(Dtd.GetElementNameFromNode(node.ParentNode), false); } } } // Check whether the current DTD run has led to one of the searched test patterns foreach (DtdTestpattern muster in allPattern) // run through all samples to be tested { if (element_ == null) { muster.Success = false; // This element is not known at all } else { if (!muster.Success) { #if DEBUGTRACE Trace.WriteLine(String.Format("Check für neues Ziel-Muster {0} > {1}", ElementName(muster.Element), muster.Zusammenfassung_)); #endif muster.Success = FitsPatternInElement(muster, element_); } } } }
private bool CheckNodePos(System.Xml.XmlNode node) { // Comment is always ok //if (node is System.Xml.XmlComment) return true; // Whitespace is always ok if (node is System.Xml.XmlWhitespace) { return(true); } if (dtd.IsDtdElementKnown(Dtd.GetElementNameFromNode(node))) // The element of this node is known in the DTD { try { if (this.NodeChecker.IsTheNodeAllowedAtThisPos(node)) { return(true); } else { errorMessages.AppendFormat($"Tag '{node.Name}' not allowed here."); var pos = new XmlCursorPos(); pos.SetPos(node, XmlCursorPositions.CursorOnNodeStartTag); var allowedTags = this.NodeChecker.AtThisPosAllowedTags(pos, false, false); // what is allowed at this position? if (allowedTags.Length > 0) { errorMessages.Append("At this position allowed:"); foreach (string tag in allowedTags) { errorMessages.AppendFormat("{0} ", tag); } } else { errorMessages.Append("No tags are allowed at this point. Probably the parent tag is already invalid."); } return(false); } } catch (Dtd.XMLUnknownElementException e) { errorMessages.AppendFormat($"unknown element '{e.ElementName}'"); return(false); } } else // The element of this node is not known in the DTD { errorMessages.AppendFormat($"unknown element '{Dtd.GetElementNameFromNode(node)}'"); return(false); } }
/// <summary> /// Is the specified element allowed at this point in the XML? /// </summary> public bool IsTheNodeAllowedAtThisPos(System.Xml.XmlNode node) { if (node.ParentNode is System.Xml.XmlDocument) { // It is the root element, this cannot be checked against the parent node, but must be compared separately. If it is the root element allowed in the DTD, then ok, otherwise not // Implementation: TO DO! return(true); } else { var cursorPos = new XmlCursorPos(); cursorPos.SetPos(node, XmlCursorPositions.CursorOnNodeStartTag); #if ThinkLogging _thinkLog = new StringBuilder(); #endif // Create the test patterns to insert for all available elements var elementName = Dtd.GetElementNameFromNode(node); var pattern = this.CreateTestPattern(elementName, cursorPos); // Pack into a test sample list and send the list for testing var list = new List <DtdTestpattern>(); list.Add(pattern); this.CheckAllTestPattern(list, cursorPos); if (pattern.Success) { #if ThinkLogging _thinkLog = new StringBuilder(); _thinkLog.Append(pattern.Summary + "\r\n"); #endif return(true); } else { return(false); } } }
/// <summary> /// Adds a test pattern /// </summary> private DtdTestpattern CreateTestPattern(string elementName, XmlCursorPos cursorPos) { DtdTestpattern testPattern; var node = cursorPos.ActualNode; System.Xml.XmlNode sibling; switch (cursorPos.PosOnNode) { case XmlCursorPositions.CursorInsideTheEmptyNode: // The parent node is empty, so we only have to test for the allowed elements in it and not expect any sibling elements on the same level testPattern = new DtdTestpattern(elementName, Dtd.GetElementNameFromNode(node)); testPattern.AddElement(elementName); break; default: // If the parent node is the XML document itself, then abort here if (node.ParentNode is System.Xml.XmlDocument) { throw new ApplicationException("No test pattern can be created for the root element. Its validity must be guaranteed by comparison with the DTD root element."); } testPattern = new DtdTestpattern(elementName, Dtd.GetElementNameFromNode(node.ParentNode)); // Traverse all elements within the parent element sibling = node.ParentNode.FirstChild; while (sibling != null) { if (sibling is System.Xml.XmlWhitespace) { // Whitespace tags can be ignored during the check } else { if (sibling == node) // at this point the node must be inserted { if (sibling is System.Xml.XmlComment) { testPattern.AddElement("#COMMENT"); } else { if (this.dtd.DTDElementByName(Dtd.GetElementNameFromNode(node), false) == null) { // This element is not known at all, therefore the element is sometimes not included // throw new ApplicationException(String.Format("unknown Node-Element '{0}'", DTD.GetElementNameFromNode(node))); } else { switch (cursorPos.PosOnNode) { case XmlCursorPositions.CursorOnNodeStartTag: // If the node itself is selected and should be replaced case XmlCursorPositions.CursorOnNodeEndTag: if (elementName == null) // check delete { // Omit element } else // check insert/replace { // Instead of the element present at this position, the element to be tested is inserted here testPattern.AddElement(elementName); } break; case XmlCursorPositions.CursorBehindTheNode: if (elementName == null) // check delete { throw new ApplicationException("CreateTestPattern: Delete must not be checked for XmlCursorPositions.CursorBehindTheNode!"); } else { // element is inserted behind the element to be tested testPattern.AddElement(Dtd.GetElementNameFromNode(node)); testPattern.AddElement(elementName); } break; case XmlCursorPositions.CursorInsideTheEmptyNode: if (elementName == null) // check delete { throw new ApplicationException("CreateTestPattern: Delete must not be checked for XmlCursorPositions.CursorInsideTheEmptyNode!"); } else { throw new ApplicationException("CreateTestPattern: CursorInsideTheEmptyNode can´t be handled at this place!"); } case XmlCursorPositions.CursorInFrontOfNode: if (elementName == null) // check delete { throw new ApplicationException("CreateTestPattern: Delete must not be checked for XmlCursorPositions.CursorInFrontOfNode!"); } else { // Element is inserted before the element to be tested testPattern.AddElement(elementName); testPattern.AddElement(Dtd.GetElementNameFromNode(node)); } break; case XmlCursorPositions.CursorInsideTextNode: if (elementName == null) // check delete { throw new ApplicationException("CreateTestPattern: Delete must not be checked for XmlCursorPositions.CursorInsideTextNode!"); } else { if (Dtd.GetElementNameFromNode(node) != "#PCDATA") { throw new ApplicationException("CreateTestPattern: CursorInsideTextNode, but node.name=" + Dtd.GetElementNameFromNode(node)); } else { // The element to be tested is placed between two text nodes testPattern.AddElement("#PCDATA"); testPattern.AddElement(elementName); testPattern.AddElement("#PCDATA"); } } break; default: throw new ApplicationException("Unknown XmlCursorPositions value:" + cursorPos.PosOnNode); } } } } else // just continue enumerating the elements as usual { testPattern.AddElement(Dtd.GetElementNameFromNode(sibling)); } } sibling = sibling.NextSibling; // to the next element } break; } return(testPattern); }