0

我正在尝试为单个 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)(?!))";



}
4

1 回答 1

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;
                    }
                }
    }
于 2013-09-18T18:23:03.687 回答