代码之家  ›  专栏  ›  技术社区  ›  GurdeepS

递归读取XML文档并使用regex获取内容

  •  1
  • GurdeepS  · 技术社区  · 15 年前

    我有一个XML文档,如下所示:

    <menuitem navigateurl="/PressCentre/" text="&#1087;&#1088;&#1077;&#1089; &#1094;&#1077;&#1085;&#1090;&#1098;&#1088;">
        <menuitem navigateurl="/PressCentre/RegisterForPressAlerts/" text="&#1088;&#1077;&#1075;&#1080;&#1089;&#1090;&#1098;&#1088; &#1079;&#1072; &#1087;&#1088;&#1077;&#1089; &#1089;&#1098;&#1086;&#1073;&#1097;&#1077;&#1085;&#1080;&#1103;" />
        <menuitem navigateurl="/PressCentre/PressReleases/" text="&#1087;&#1088;&#1077;&#1089; &#1089;&#1098;&#1086;&#1073;&#1097;&#1077;&#1085;&#1080;&#1103;">
            <menuitem navigateurl="/PressCentre/PressReleases/PressReleasesArchive/" text="&#1072;&#1088;&#1093;&#1080;&#1074; &#1087;&#1088;&#1077;&#1089; &#1089;&#1098;&#1086;&#1073;&#1097;&#1077;&#1085;&#1080;&#1103;" />
        </menuitem>
        <menuitem navigateurl="/PressCentre/PressKit/" text="&#1087;&#1088;&#1077;&#1089; &#1082;&#1086;&#1084;&#1087;&#1083;&#1077;&#1082;&#1090;">
            <menuitem navigateurl="/PressCentre/PressKit/FactSheets/" text="&#1089;&#1087;&#1080;&#1089;&#1098;&#1082; &#1092;&#1072;&#1082;&#1090;&#1080;" />
            <menuitem navigateurl="/PressCentre/PressKit/ExpertComments/" text="&#1082;&#1086;&#1084;&#1077;&#1085;&#1090;&#1072;&#1088;&#1080; &#1085;&#1072; &#1077;&#1082;&#1089;&#1087;&#1077;&#1088;&#1090;&#1080;" />
            <menuitem navigateurl="/PressCentre/PressKit/Testimonials/" text="&#1087;&#1088;&#1077;&#1087;&#1086;&#1088;&#1098;&#1082;&#1080;" />
            <menuitem navigateurl="/PressCentre/PressKit/MediaFiles/" text="&#1084;&#1077;&#1076;&#1080;&#1103; &#1092;&#1072;&#1081;&#1083;&#1086;&#1074;&#1077;" />
            <menuitem navigateurl="/PressCentre/PressKit/Photography/" text="&#1089;&#1085;&#1080;&#1084;&#1082;&#1080;" />
        </menuitem>
        <menuitem navigateurl="/PressCentre/PressContacts/" text="&#1087;&#1088;&#1077;&#1089; &#1082;&#1086;&#1085;&#1090;&#1072;&#1082;&#1090;&#1080;" />
    </menuitem>
    

    我需要在navigateurl(例如“/presscenter”)之间获取值。有没有一个著名的regex脚本来做这个?

    谢谢

    6 回复  |  直到 12 年前
        1
  •  6
  •   annakata    15 年前

    基本递归(未测试,但我认为可以):

    private void Caller(String filepath)
    {
        XPathDocument oDoc = new XPathDocument(filepath);
        Readnodes( oDoc.CreateNavigator() );
    }
    
    private void ReadNodes(XPathNavigator nav)
    {
        XPathNodeIterator nodes = nav.Select("menuitem");
        while (nodes.MoveNext())
        {
            //A - read the attribute
            string url = nodes.Current.GetAttribute("navigateurl", string.Empty);
    
            //B - do something with the data
    
            //C - recurse
            ReadNodes(nodes.Current);
        }
    }
    

    …有效,因为xpathnodeiterator的当前属性也是xpathnavigator。显然,您需要扩展这个功能,以便将数据推送到字典中,或者跟踪深度等。

        2
  •  1
  •   ZombieSheep    15 年前

    当xpath(至少对我来说)是自然选择时,为什么要使用regex呢?这就是XSLT应该实现的…

        3
  •  0
  •   Rad    15 年前

    你使用regex有什么特别的原因吗?是否尝试使用xpath?下面是一些如何使用xpath的示例。 http://www.w3schools.com/XPath/xpath_examples.asp

        4
  •  0
  •   JavaRocky    15 年前

    使用xpath,//menuitem[@navigateurl]/@navigateurl。

    此xpath将获取具有naviagate url属性的所有菜单项,并返回navigateurl值的节点列表(xpath 1.0)或序列(xpath 2.0)。通过使用navigateURL属性谓词,确保只获取叶菜单项。

        5
  •  0
  •   Hardryv    13 年前

    我的帖子提出了一个特定的需求,与OP的询问有关,但没有具体的OP的要求。当我需要时,我喜欢regex和递归,但在本例中,我认为op的查询目标是学习一种生成正确格式的XML输出的方法,我在下面提供的是在没有大量上下文源代码开发的情况下(为什么要重新设计轮子?)在.NET 2.0框架的后面支持和。

    在我的工作中,我经常以支持现代政府制度而告终。这些系统通常仍然只支持部署系统上的2.0版本——主要是出于安全考虑。2.0框架缺少最新.NET版本的一些优美输出,特别是在涉及XML对象的情况下。下面设置的完全有效的方法对我来说是很有价值和节省时间的,我将它提供给那些为政府利益服务的不可见的开发人员同志。

    此外,您还可以使用LinqBridge库来提供有限的Linq支持(从3.5 Service Pack到3.5 Service Pack,实际上内部自评估为2.0,因此LinqBridge的构造是为了弥补特定的差距(在使用Visual Studio 2008开发为2.0 Build时限制了Linq查询支持)。但是,请注意,目前不支持将LinqBridge转发到Visual Studio 2008。

    为了最大限度地减少包发布大小,并与我提供服务的组织要求保持兼容,我避免使用关联的非XML库(如regex)来解析XML并坚持使用标准的XML对象。尤其是旧的xml*前缀对象与更现代(更灵活)的x*前缀对象…

    下面,我提供了许多安全、简单、高效的方法,可以从各种标准2.0XML*对象生成格式化的XML。还要注意,这些函数的工作马实际上是xpathnavigator类,而不是它的兄弟类。

    下面是一个调用示例方法的C代码片段:

    doc = new XmlDocument();
    doc.Load(Input_FilePath);
    sb = StringBuilderFromXmlDocument(doc);
    Out(sb);
    sb = StringBuilderFromXPathDocument(new XPathDocument(Input_FilePath));
    Out(sb);
    sb = StringBuilderFromXPathNavigator(new XPathDocument(Input_FilePath).CreateNavigator());
    Out(sb);
    ss = StringFromXmlDocument(doc);
    Out(ss);
    ss = StringFromXPathDocument(new XPathDocument(Input_FilePath));
    Out(ss);
    ss = StringFromXPathNavigator(new XPathDocument(Input_FilePath).CreateNavigator());
    Out(ss);
    

    下面是示例方法,其中一个方法很可能满足您的XML格式需求:

    public static StringBuilder StringBuilderFromXmlDocument(XmlDocument _xd)
    {
        XPathNavigator _xpn;
        try
        {
            _xpn = _xd.CreateNavigator();
        }
        catch
        {
            _xd.LoadXml(DEFAULT_ERROR_TEXT);
            _xpn = _xd.CreateNavigator();
        }
        return StringBuilderFromXPathNavigator(_xpn);
    }
    
    private static StringBuilder StringBuilderFromXPathDocument(XPathDocument _xpd)
    {
        StringBuilder returnVal = new StringBuilder();
        XPathNavigator _xpn;
        try
        {
            _xpn = _xpd.CreateNavigator();
            returnVal.AppendLine(_xpn.OuterXml.Trim());
        }
        catch
        {
            returnVal = new StringBuilder()
                .Append(DEFAULT_ERROR_TEXT);
        }
        return returnVal;
    }
    
    private static StringBuilder StringBuilderFromXPathNavigator(XPathNavigator _xpn)
    {
        StringBuilder returnVal = new StringBuilder();
        try
        {
            returnVal.AppendLine(_xpn.OuterXml.Trim());
        }
        catch
        {
            returnVal = new StringBuilder()
                .Append(DEFAULT_ERROR_TEXT);
        }
        return returnVal;
    }
    
    public static string StringFromXmlDocument(XmlDocument _xd)
    {
        XPathNavigator _xpn;
        try
        {
            _xpn = _xd.CreateNavigator();
        }
        catch
        {
            _xd.LoadXml(DEFAULT_ERROR_TEXT);
            _xpn = _xd.CreateNavigator();
        }
        return StringFromXPathNavigator(_xpn);
    }
    
    private static string StringFromXPathNavigator(XPathNavigator _xpn)
    {
        string returnVal;
        try
        {
            returnVal = _xpn.OuterXml.Trim();
        }
        catch
        {
            returnVal = DEFAULT_ERROR_TEXT;
        }
        returnVal = _xpn.OuterXml.Trim();
        return returnVal;
    }
    
    private static string StringFromXPathDocument(XPathDocument _xpd)
    {
        string returnVal;
        XPathNavigator _xpn;
        try
        {
            _xpn = _xpd.CreateNavigator();
            returnVal = _xpn.OuterXml.Trim();
        }
        catch
        {
            returnVal = DEFAULT_ERROR_TEXT;
        }
        return returnVal;
    }
    

    享受。^ ^

    请注意,在以后的框架版本和使用较新的Xelement对象时,您可以for each()Xelement的节点和.toString()的每个结果自动进行正确的格式设置。就像我上面说的,更优雅了:)。

        6
  •  0
  •   Peter O. Manuel Pinto    12 年前

    如何使用Java中的正则表达式递归读取XML文档

    public static void main(String[] args) {
            String data**="<CheckExistingDSLService>" +
                    "<DSLPN>4137361787</DSLPN>" +
                    "<DSLPN>8566944014</DSLPN>" +
                    "<ClientRequestId>CRID</ClientRequestId>" +
                    "<DSLPN>8566944024</DSLPN>" +
                    "<ClientSystemId>SSPORD</ClientSystemId>" +
                    "<Authentication>" +
                    "<Id>SSPORD</Id>" +
                    "</Authentication>" +
                    "<Comment>Service to check CheckExistingDSL</Comment>"** +
                    "</CheckExistingDSLService>";
            System.out.print("The dats is "+listDataElements(data));
    
        }
        private static final Pattern PATTERN_1 = Pattern.compile("<([^<>]+)>([^<>]+)</\\1>"); 
        private static List<String> listDataElements(CharSequence cs) {     
            List<String> list = new ArrayList<String>();     
            Matcher matcher = PATTERN_1.matcher(cs);    
            while (matcher.find()) {         
                if(matcher.group(1).equalsIgnoreCase("DSLPN")){
                    try{
                        Long number=Long.parseLong(matcher.group(2));
                        list.add(number.toString());
    
                    }catch(Exception e){
                        System.out.println("Do noting this is notnumber ");                 
                    }
                }
            } return list; 
        }
    

    您将得到的输出:日期是[4137361787,8566944014,8566944024]