递归读取xml文档并使用正则表达式获取内容

时间:2009-05-05 15:33:43

标签: xml regex xslt

我有一个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之间的值(例如“/ PressCentre”)。是否有一个众所周知的正则表达式脚本来执行此操作?

由于

6 个答案:

答案 0 :(得分:6)

一个基本的递归(未经测试,但我认为没关系):

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的Current属性也是XPathNavigator而起作用。显然,你需要扩展它以将数据推送到字典或跟踪深度或其他任何内容。

答案 1 :(得分:1)

为什么在XPath(对我来说,至少是)自然选择的时候使用正则表达式呢?这基本上就是XSLT应该实现的......

答案 2 :(得分:0)

您使用正则表达式的任何特殊原因?您是否尝试过使用XPath?以下是如何使用XPath的一些示例。 http://www.w3schools.com/XPath/xpath_examples.asp

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

我的帖子解决了与OP的调查相关的特定需求,但没有具体说明OP所询问的内容。当我需要它时,我喜欢正则表达式和递归,但在这种情况下,我认为OP的调查的目的是学习一种生成格式正确的XML输出的方法,而我在下面提供的内容确实没有重大的上下文源代码开发(为什么要重新发明轮子?)并在.NET 2.0框架中得到支持。

在我的工作中,我经常最终支持现代政府系统。这些系统通常仍然只支持部署系统上的2.0 - 主要是出于安全考虑。 2.0 Framework缺少最新.NET版本的一些优雅输出,特别是在涉及XML对象的情况下。下面完全验证的方法集对我来说非常有价值且节省时间,我为那些也为政府利益服务的看不见的开发者同志提供了这些方法。

此外,您还可以利用LinqBridge库获得有限的Linq支持(.NET up到3.5 service-pack实际上内部自我评估为2.0,因此构建LinqBridge以弥合特定差距(开发到2.0版本时,Linq查询支持有限)使用Visual Studio 2008。但请注意,LinqBridge目前不支持Visual Studio 2008。

为了最小化包发布大小并且与我提供服务的组织要求保持兼容,我避免使用关联非XML库(例如Regex)来解析XML并坚持使用标准XML对象。特别是较旧的Xml * -prefix对象与更现代(和更灵活)的X * -prefix对象...

下面我提供了许多安全,简单,高效的方法,可以从各种标准的2.0 Xml *对象生成格式化的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;
}

享受。 ^^

请注意,在以后的Framework版本中并使用较新的XElement对象,您可以foreach(){} XElement的节点和.ToString()每个结果以自动正确格式化。就像我上面说的那样,更加优雅:)。

答案 5 :(得分:0)

如何使用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]