正则表达式XML解析C#

时间:2013-09-18 18:10:36

标签: c# xml regex

我正在尝试为单个XML块构建一个正则表达式解析器。

我知道人们会说Regex不是一个很好的xml计划,但是我正在使用流数据,我只需要知道是否已经广播了一个完整的xml块并且是否位于缓冲区中。

我正在尝试处理XML的开始和结束块之间的任何内容以及主块头的参数中的任何数据。

我的示例代码位于细分的正则表达式之下,如果有人有任何关于如何使其尽可能全面的输入,我将非常感激。

这是我为视觉辅助格式化的正则表达式。

我正在平衡组和组,并验证它们在表达式段的末尾不存在。

/*
   ^(?<TAG>[<]
        (?![?])
        (?<TAGNAME>[^\s/>]*)
    )
    (?<ParamData>
        (
            (\"
                (?>
                    \\\"|
                    [^"]|
                    \"(?<quote>)|
                    \"(?<-quote>)
                )*
                (?(quote)(?!))
                \"
            )|
            [^/>]
        )*?
    )
    (?:
        (?<HASCONTENT>[>])|
        (?<-TAG>
            (?<TAGEND>/[>])
        )
    )
    (?(HASCONTENT)
        (
            (?<CONTENT>
                (
                    (?<inTAG>[<]\<TAGNAME>)(?<-inTAG>/[>])?|
                    (?<-inTAG>[<]/\<TAGNAME>[>])|
                    ([^<]+|[<](?![/]?\<TAGNAME>))
                )*?
                (?(inTAG)(?!))
            )
        )
        (?<TAGEND>(?<-TAG>)[<]/\<TAGNAME>[>])
    )
    (?(TAG)(?!))
*/

在我的课程中,我希望返回任何Null对象意味着队列中没有xml块。

这是我正在使用的课程。

(我使用文字字符串(@“”)来限制转义要求,所有“字符都替换为”“以正确格式化。

public class XmlDataParser
{
    // xmlObjectExpression defined below to limit code highlight errors
    private Regex _xmlRegex;
    private Regex xmlRegex
    {
        get
        {
            if (_xmlRegex == null)
            {
                _xmlRegex = new Regex(xmlObjectExpression);
            }
            return _xmlRegex;
        }
    }

    private string backingStore = "";

    public bool HasObject()
    {
        return (backingStore != null) && xmlRegex.IsMatch(backingStore);
    }
    public string GetObject()
    {
        string result = null;
        if (HasObject())
        {
            lock (this)
            {
                Match obj = xmlRegex.Match(backingStore);
                result = obj.Value;
                backingStore = backingStore.Substring(result.Length);
            }
        }
        return result;
    }

    public void AddData(byte[] bytes)
    {
        lock (this)
        {
            backingStore += System.Text.Encoding.Default.GetString(bytes);
        }
    }

    private static string xmlObjectExpression = @"^(?<TAG>[<](?![?])(?<TAGNAME>[^\s/>]*))(?<ParamData>((\""(?>\\\""|[^""]|\""(?<quote>)|\""(?<-quote>))*(?(quote)(?!))\"")|[^/>])*?)(?:(?<HASCONTENT>[>])|(?<-TAG>(?<TAGEND>/[>])))(?(HASCONTENT)((?<CONTENT>((?<inTAG>[<]\<TAGNAME>)(?<-inTAG>/[>])?|(?<-inTAG>[<]/\<TAGNAME>[>])|([^<]+|[<](?![/]?\<TAGNAME>)))*?(?(inTAG)(?!))))(?<TAGEND>(?<-TAG>)[<]/\<TAGNAME>[>]))(?(TAG)(?!))";



}

1 个答案:

答案 0 :(得分:4)

只需使用XmlReader并将其作为TextReader。要读取流,您需要将ConformanceLevel更改为Fragment。

    XmlReaderSettings settings = new XmlReaderSettings();
    settings.ConformanceLevel = ConformanceLevel.Fragment;
    using (XmlReader reader = XmlReader.Create(tr,settings))
    {
               while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
// this is from my code. You'll rewrite this part :

                        case XmlNodeType.Element:
                            if (t != null)
                            {
                                t.SetName(reader.Name);
                            }
                            else if (reader.Name == "event")
                            {
                                t = new Event1();
                                t.Name = reader.Name;
                            }
                            else if (reader.Name == "data")
                            {
                                t = new Data1();
                                t.Name = reader.Name;
                            }
                            else
                            {
                                throw new Exception("");
                            }

                            break;
                        case XmlNodeType.Text:
                            if (t != null)
                            {
                                t.SetValue(reader.Value);
                            }
                            break;
                        case XmlNodeType.XmlDeclaration:
                        case XmlNodeType.ProcessingInstruction:
                            break;
                        case XmlNodeType.Comment:
                            break;
                        case XmlNodeType.EndElement:
                            if (t != null)
                            {
                                if (t.Name == reader.Name)
                                {

                                    t.Close();
                                    t.Write(output);
                                    t = null;
                                }
                            }

                            break;
                        case XmlNodeType.Whitespace:
                            break;
                    }
                }
    }