Custom xmlWriter to skip a certain element?

前端 未结 1 1232
隐瞒了意图╮
隐瞒了意图╮ 2020-12-04 03:42

I am implementing a custom xmlwriter and I want to omit any elements with a particular name, like .

How do I actually do that? I get a sense

相关标签:
1条回答
  • 2020-12-04 04:49

    Found this in some sample code I wrote previously. It maintains a push-down stack to determine whether to write the element end, which is what you would need to do:

    public class ElementSkippingXmlTextWriter : XmlWriterProxy
    {
        readonly Stack<bool> stack = new Stack<bool>();
        readonly Func<string, string, int, bool> filter;
        readonly Func<string, string, int, string> nameEditor;
        readonly bool filterChildren;
    
        public ElementSkippingXmlTextWriter(XmlWriter writer, Func<string, string, int, bool> filter, bool filterChildren)
            : this(writer, filter, null, filterChildren)
        {
        }
    
        public ElementSkippingXmlTextWriter(XmlWriter writer, Func<string, string, int, bool> filter, Func<string, string, int, string> nameEditor, bool filterChildren)
            : base(writer)
        {
            this.filter = filter ?? delegate { return true; };
            this.nameEditor = nameEditor ?? delegate(string localName, string ns, int depth) { return localName; };
            this.filterChildren = filterChildren;
        }
    
        protected override bool IsSuspended
        {
            get
            {
                if (filterChildren)
                {
                    if (!stack.All(b => b))
                        return true;
                }
                else
                {
                    if (stack.Count > 0 && !stack.Peek())
                        return true;
                }
    
                return base.IsSuspended;
            }
        }
    
        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            var write = filter(localName, ns, stack.Count);
            var newLocalName = nameEditor(localName, ns, stack.Count);
            if (write)
                base.WriteStartElement(prefix, newLocalName, ns);
            stack.Push(write);
        }
    
        public override void WriteEndElement()
        {
            if (stack.Pop())
                base.WriteEndElement();
        }
    }
    
    public class XmlWriterProxy : XmlWriter
    {
        readonly XmlWriter baseWriter;
    
        public XmlWriterProxy(XmlWriter baseWriter)
        {
            if (baseWriter == null)
                throw new ArgumentNullException();
            this.baseWriter = baseWriter;
        }
    
        protected virtual bool IsSuspended { get { return false; } }
    
        public override void Close()
        {
            baseWriter.Close();
        }
    
        public override void Flush()
        {
            baseWriter.Flush();
        }
    
        public override string LookupPrefix(string ns)
        {
            return baseWriter.LookupPrefix(ns);
        }
    
        public override void WriteBase64(byte[] buffer, int index, int count)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteBase64(buffer, index, count);
        }
    
        public override void WriteCData(string text)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteCData(text);
        }
    
        public override void WriteCharEntity(char ch)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteCharEntity(ch);
        }
    
        public override void WriteChars(char[] buffer, int index, int count)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteChars(buffer, index, count);
        }
    
        public override void WriteComment(string text)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteComment(text);
        }
    
        public override void WriteDocType(string name, string pubid, string sysid, string subset)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteDocType(name, pubid, sysid, subset);
        }
    
        public override void WriteEndAttribute()
        {
            if (IsSuspended)
                return;
            baseWriter.WriteEndAttribute();
        }
    
        public override void WriteEndDocument()
        {
            if (IsSuspended)
                return;
            baseWriter.WriteEndDocument();
        }
    
        public override void WriteEndElement()
        {
            if (IsSuspended)
                return;
            baseWriter.WriteEndElement();
        }
    
        public override void WriteEntityRef(string name)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteEntityRef(name);
        }
    
        public override void WriteFullEndElement()
        {
            if (IsSuspended)
                return;
            baseWriter.WriteFullEndElement();
        }
    
        public override void WriteProcessingInstruction(string name, string text)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteProcessingInstruction(name, text);
        }
    
        public override void WriteRaw(string data)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteRaw(data);
        }
    
        public override void WriteRaw(char[] buffer, int index, int count)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteRaw(buffer, index, count);
        }
    
        public override void WriteStartAttribute(string prefix, string localName, string ns)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteStartAttribute(prefix, localName, ns);
        }
    
        public override void WriteStartDocument(bool standalone)
        {
            baseWriter.WriteStartDocument(standalone);
        }
    
        public override void WriteStartDocument()
        {
            baseWriter.WriteStartDocument();
        }
    
        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteStartElement(prefix, localName, ns);
        }
    
        public override WriteState WriteState
        {
            get { return baseWriter.WriteState; }
        }
    
        public override void WriteString(string text)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteString(text);
        }
    
        public override void WriteSurrogateCharEntity(char lowChar, char highChar)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteSurrogateCharEntity(lowChar, highChar);
        }
    
        public override void WriteWhitespace(string ws)
        {
            if (IsSuspended)
                return;
            baseWriter.WriteWhitespace(ws);
        }
    }
    

    It wraps an XmlWriter you would create as usual with a call to XmlWriter.Create(), and filters elements (and, optionally, children) for which the filter delegate returns false.

    Note -- not fully tested. Async methods may need to be overridden as well.

    0 讨论(0)
提交回复
热议问题