mirror of
				https://github.com/Theodor-Springmann-Stiftung/hamann-ausgabe-core.git
				synced 2025-10-30 17:55:32 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			175 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using HaXMLReader.EvArgs;
 | |
| using System.Linq;
 | |
| using System.IO;
 | |
| using System.Xml;
 | |
| using System.Collections;
 | |
| using System.ComponentModel;
 | |
| using System.Collections.Generic;
 | |
| using HaXMLReader.Interfaces;
 | |
| 
 | |
| namespace HaXMLReader
 | |
| {
 | |
|     public abstract class Reader : IReader
 | |
|     {
 | |
|         public event EventHandler ReadingStart;
 | |
|         public event EventHandler ReadingStop;
 | |
|         public event EventHandler<Tag> Tag;
 | |
|         public event EventHandler<Tag> OpenTag;
 | |
|         public event EventHandler<Tag> CloseTag;
 | |
|         public event EventHandler<Tag> SingleTag;
 | |
|         public event EventHandler<Whitespace> Whitespace;
 | |
|         public event EventHandler<Text> Text;
 | |
| 
 | |
|         protected Action<string[]> _LogSink { get; set; }
 | |
|         private XmlReader _XReader { get; set; } = null;
 | |
| 
 | |
|         //State:
 | |
|         internal XmlReaderSettings _Settings = new XmlReaderSettings()
 | |
|         {
 | |
|             CloseInput = true,
 | |
|             CheckCharacters = false,
 | |
|             ConformanceLevel = ConformanceLevel.Fragment,
 | |
|             IgnoreComments = true,
 | |
|             IgnoreProcessingInstructions = true,
 | |
|             IgnoreWhitespace = false
 | |
|         };
 | |
| 
 | |
|         public void Log(params string[] message)
 | |
|         {
 | |
|             if (_LogSink != null) _LogSink.Invoke(message.Select(x => x = "HamannDocument: \t" + x).ToArray());
 | |
|         }
 | |
| 
 | |
|         public void Read()
 | |
|         {
 | |
|             if (_XReader == null || 
 | |
|                 _XReader.ReadState == ReadState.Closed || 
 | |
|                 _XReader.ReadState == ReadState.EndOfFile ||
 | |
|                 _XReader.ReadState == ReadState.Error) {
 | |
|                     CreateReader();
 | |
|             }
 | |
|             ReadingStart?.Invoke(this, EventArgs.Empty);
 | |
|             while (_XReader.Read())
 | |
|             {
 | |
|                 _Read();
 | |
|             }
 | |
|             ReadingStop?.Invoke(this, EventArgs.Empty);
 | |
|             Dispose();
 | |
|         }
 | |
| 
 | |
|         private void _Read() {
 | |
|             try {
 | |
|                 switch (_XReader.NodeType)
 | |
|                 {
 | |
|                     case XmlNodeType.Text:
 | |
|                         Text?.Invoke(this, new Text() { Value = _XReader.Value });
 | |
|                         break;
 | |
|                     case XmlNodeType.SignificantWhitespace:
 | |
|                         Whitespace?.Invoke(this, new Whitespace() { Value = _XReader.Value });
 | |
|                         break;
 | |
|                     case XmlNodeType.Whitespace:
 | |
|                         Whitespace?.Invoke(this, new Whitespace() { Value = _XReader.Value });
 | |
|                         break;
 | |
|                     case XmlNodeType.Element:
 | |
|                         var tag = _TagCreation();
 | |
|                         Tag?.Invoke(this, tag);
 | |
|                         if (tag.IsEmpty) SingleTag?.Invoke(this, tag);
 | |
|                         else OpenTag?.Invoke(this, tag);
 | |
|                         break;
 | |
|                     case XmlNodeType.EndElement:
 | |
|                         var tg = _TagCreation();
 | |
|                         Tag?.Invoke(this, tg);
 | |
|                         CloseTag?.Invoke(this, tg);
 | |
|                         break;
 | |
|                 }
 | |
|             }
 | |
|             catch (XmlException ex) {
 | |
|                 Log(ex.Message);
 | |
|                 throw ex;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public IReader CreateReaderForSubtree(string elementname) {
 | |
|             if (_XReader == null) CreateReader();
 | |
|             else throw new InvalidOperationException("Der Status des Readers kann nicht verändert werden.");
 | |
|             _skipUntilElement(elementname);
 | |
|             return _createReaderForSubtree();
 | |
|         }
 | |
| 
 | |
|         public IReader CreateReaderForSubtree(Func<Tag, bool> Condition) {
 | |
|             if (_XReader == null) CreateReader();
 | |
|             else throw new InvalidOperationException("Der Status des Readers kann nicht verändert werden.");
 | |
|             while (_XReader.Read()) {
 | |
|                 if(_XReader.NodeType == XmlNodeType.Element) {
 | |
|                     var tag = _TagCreation();
 | |
|                     if (Condition(tag))
 | |
|                         return _createReaderForSubtree();
 | |
|                 }
 | |
|             }
 | |
|             return null;
 | |
|         }
 | |
| 
 | |
|         private IReader _createReaderForSubtree() {
 | |
|             if (_XReader.NodeType == XmlNodeType.Attribute)
 | |
|                 _XReader.MoveToElement();
 | |
|             return new XmlReaderReader(_XReader.ReadSubtree());
 | |
|         }
 | |
| 
 | |
|         public void ImportSettings(XmlReaderSettings settings) {
 | |
|             _Settings = settings;
 | |
|         }
 | |
| 
 | |
|         public virtual void Dispose() {
 | |
|         }
 | |
| 
 | |
|         // Legacy:
 | |
|         public void Close() {
 | |
|             _XReader.Close();
 | |
|         }
 | |
| 
 | |
|         protected void CreateReader() {
 | |
|             if (_XReader == null || 
 | |
|                 _XReader.ReadState == ReadState.Closed || 
 | |
|                 _XReader.ReadState == ReadState.EndOfFile ||
 | |
|                 _XReader.ReadState == ReadState.Error) {
 | |
|                 _XReader = GetReader();
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         protected abstract XmlReader GetReader();
 | |
| 
 | |
|         private void _skipUntilElement(string name) {
 | |
|             if (_XReader == null) CreateReader();
 | |
|             else throw new InvalidOperationException("Der Status des Readers kann nicht verändert werden.");
 | |
|             _XReader.ReadToFollowing(name);
 | |
|         }
 | |
| 
 | |
|         private Tag _TagCreation() {
 | |
|             var tag = new Tag();
 | |
|             tag.Name = _XReader.Name;
 | |
|             tag.IsEmpty = _XReader.IsEmptyElement;
 | |
|             tag.EndTag = _XReader.NodeType == XmlNodeType.EndElement ? true : false;
 | |
|             if (_XReader.HasAttributes)
 | |
|             {                
 | |
|                 int no = _XReader.AttributeCount;
 | |
|                 for (int step = 0; step < no; step++)
 | |
|                 {
 | |
|                     _XReader.MoveToAttribute(step);
 | |
|                     tag.Values.Add(_XReader.Name.ToLower(), _XReader.Value);
 | |
|                 }
 | |
|             }
 | |
|             return tag;
 | |
|         }
 | |
| 
 | |
|         private void _checkReadStateInteractive() {
 | |
|             if (_XReader != null && _XReader.ReadState != ReadState.Interactive) {
 | |
|                 Dispose();
 | |
|                 var ex = new InvalidOperationException("The Reader is currently not in a reading state");
 | |
|                 Log(ex.Message);
 | |
|                 throw ex;
 | |
|             }
 | |
|             return;
 | |
|         }
 | |
|     }
 | |
| }
 | 
