/// <summary> /// Performs validation on the xml source as well as evaluates conditional and flow expresions /// </summary> /// <exception cref=".">For invalid use of conditional expressions or for invalid XML syntax. If a XmlValidatingReader is passed, then will also throw exceptions for non-schema-conforming xml</exception> /// <param name="reader"></param> /// <returns>the output xml </returns> public string Process(XmlReader reader) { if(reader == null) throw new ArgumentException("Invalid XML reader to pre-process"); IfContext context = new IfContext(true, true, IfState.None); StringWriter xmlText = new StringWriter(); XmlTextWriter writer = new XmlTextWriter(xmlText); writer.Formatting = Formatting.Indented; while(reader.Read()) { if(reader.NodeType == XmlNodeType.ProcessingInstruction) { bool ignore = false; switch(reader.LocalName) { case "if": m_IfStack.Push(context); context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If); ignore = true; break; case "elseif": if(m_IfStack.Count == 0) throw new WarningException("Unexpected 'elseif' outside of 'if'"); else if(context.State != IfState.If && context.State != IfState.ElseIf) throw new WarningException("Unexpected 'elseif' outside of 'if'"); context.State = IfState.ElseIf; if(!context.EverKept) context.Keep = ParseExpression(reader.Value); else context.Keep = false; ignore = true; break; case "else": if(m_IfStack.Count == 0) throw new WarningException("Unexpected 'else' outside of 'if'"); else if(context.State != IfState.If && context.State != IfState.ElseIf) throw new WarningException("Unexpected 'else' outside of 'if'"); context.State = IfState.Else; context.Keep = !context.EverKept; ignore = true; break; case "endif": if(m_IfStack.Count == 0) throw new WarningException("Unexpected 'endif' outside of 'if'"); context = (IfContext)m_IfStack.Pop(); ignore = true; break; } if(ignore) continue; }//end pre-proc instruction if(!context.Active || !context.Keep) continue; switch(reader.NodeType) { case XmlNodeType.Element: bool empty = reader.IsEmptyElement; writer.WriteStartElement(reader.Name); while (reader.MoveToNextAttribute()) writer.WriteAttributeString(reader.Name, reader.Value); if(empty) writer.WriteEndElement(); break; case XmlNodeType.EndElement: writer.WriteEndElement(); break; case XmlNodeType.Text: writer.WriteString(reader.Value); break; case XmlNodeType.CDATA: writer.WriteCData(reader.Value); break; default: break; } } if(m_IfStack.Count != 0) throw new WarningException("Mismatched 'if', 'endif' pair"); return xmlText.ToString(); }
/// <summary> /// Performs validation on the xml source as well as evaluates conditional and flow expresions /// </summary> /// <exception cref=".">For invalid use of conditional expressions or for invalid XML syntax. If a XmlValidatingReader is passed, then will also throw exceptions for non-schema-conforming xml</exception> /// <param name="reader"></param> /// <returns>the output xml </returns> public string Process(XmlReader reader) { if (reader == null) { throw new ArgumentException("Invalid XML reader to pre-process"); } IfContext context = new IfContext(true, true, IfState.None); StringWriter xmlText = new StringWriter(); XmlTextWriter writer = new XmlTextWriter(xmlText); writer.Formatting = Formatting.Indented; while (reader.Read()) { if (reader.NodeType == XmlNodeType.ProcessingInstruction) { bool ignore = false; switch (reader.LocalName) { case "if": m_IfStack.Push(context); context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If); ignore = true; break; case "elseif": if (m_IfStack.Count == 0) { throw new WarningException("Unexpected 'elseif' outside of 'if'"); } else if (context.State != IfState.If && context.State != IfState.ElseIf) { throw new WarningException("Unexpected 'elseif' outside of 'if'"); } context.State = IfState.ElseIf; if (!context.EverKept) { context.Keep = ParseExpression(reader.Value); } else { context.Keep = false; } ignore = true; break; case "else": if (m_IfStack.Count == 0) { throw new WarningException("Unexpected 'else' outside of 'if'"); } else if (context.State != IfState.If && context.State != IfState.ElseIf) { throw new WarningException("Unexpected 'else' outside of 'if'"); } context.State = IfState.Else; context.Keep = !context.EverKept; ignore = true; break; case "endif": if (m_IfStack.Count == 0) { throw new WarningException("Unexpected 'endif' outside of 'if'"); } context = (IfContext)m_IfStack.Pop(); ignore = true; break; } if (ignore) { continue; } } //end pre-proc instruction if (!context.Active || !context.Keep) { continue; } switch (reader.NodeType) { case XmlNodeType.Element: bool empty = reader.IsEmptyElement; writer.WriteStartElement(reader.Name); while (reader.MoveToNextAttribute()) { writer.WriteAttributeString(reader.Name, reader.Value); } if (empty) { writer.WriteEndElement(); } break; case XmlNodeType.EndElement: writer.WriteEndElement(); break; case XmlNodeType.Text: writer.WriteString(reader.Value); break; case XmlNodeType.CDATA: writer.WriteCData(reader.Value); break; default: break; } } if (m_IfStack.Count != 0) { throw new WarningException("Mismatched 'if', 'endif' pair"); } return(xmlText.ToString()); }