Рекурсивное чтение XML-документа и использование регулярных выражений для получения содержимого. - PullRequest
1 голос
/ 05 мая 2009

У меня есть 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"). Для этого есть хорошо известный скрипт regex?

Спасибо

Ответы [ 6 ]

6 голосов
/ 05 мая 2009

Базовая рекурсия (не тестировалась, но я думаю, что все в порядке):

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);
    }
}

... работает, потому что свойство Current XPathNodeIterator также является XPathNavigator. Очевидно, вам нужно расширить это, чтобы передать данные в словарь или отслеживать глубину или что-то еще.

1 голос
/ 05 мая 2009

Зачем использовать Regex для этого, когда XPath (для меня, по крайней мере) естественный выбор? Это в основном то, что XSLT должен реализовать ...

0 голосов
/ 14 февраля 2012

Как рекурсивно читать XML-документ с помощью регулярных выражений в Java

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]

0 голосов
/ 26 октября 2011

Мое сообщение посвящено конкретной потребности, связанной с запросом ОП, но не конкретно тому, что спросил ОП. Мне нравятся и Regex, и рекурсия, когда они мне нужны, но в этом случае я думаю, что цель запроса OP состояла в том, чтобы научиться генерировать правильно отформатированный вывод XML, и то, что я предоставил ниже, делает именно это без тяжелого контекста. разработка исходного кода (зачем изобретать велосипед?) и поддерживается обратно в .NET 2.0 framework.

В своей работе я часто оказываю поддержку современным государственным системам. Эти системы часто все еще поддерживают до версии 2.0 только в системах развертывания - главным образом по соображениям безопасности. В платформе 2.0 отсутствуют некоторые изящные результаты более поздних выпусков .NET, особенно когда речь идет об объектах XML. Полностью утвержденный метод, приведенный ниже, был для меня ценным и экономил время, и я предлагаю его для невидимых товарищей-разработчиков, которые также обслуживают интересы правительства.

Кроме того, вы также можете использовать библиотеки LinqBridge для ограниченной поддержки Linq (пакет обновления .NET до версии 3.5 фактически самооценки до 2.0, поэтому LinqBridge был сконструирован для преодоления этого конкретного пробела (ограниченная поддержка запросов Linq при разработке до сборки 2.0, в то время как с использованием Visual Studio 2008). Однако обратите внимание, что LinqBridge в настоящее время не поддерживается пересылкой Visual Studio 2008.

Чтобы минимизировать размеры публикаций пакетов, а также оставаться совместимыми с организационными требованиями, в которых я предоставляю свои услуги, я избегаю использования ассоциативных не XML-библиотек (таких как Regex) для анализа XML и придерживаюсь стандартных объектов XML. В частности, старые объекты Xml * -prefix против более современных (и гораздо более гибких) объектов X * -prefix ...

Ниже я приведу многочисленные безопасные, простые и эффективные методы, которые генерируют форматированный XML из ассортимента стандартных объектов Xml * 2.0. Также обратите внимание, что рабочей лошадкой для этих функций на самом деле является класс 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 () каждый для автоматического правильного форматирования. Как я уже говорил выше, гораздо более изящно:).

0 голосов
/ 06 мая 2009

Используйте xpath, // menuitem [@navigateurl] / @ navigateurl.

Этот xpath будет захватывать все пункты меню, имеющие атрибут naviagate url, и возвращать список узлов (xpath 1.0) или последовательность (xpath 2.0) значений navigateurl. Наличие предиката атрибута navigateurl гарантирует, что будут выбраны только конечные элементы меню.

0 голосов
/ 05 мая 2009

По какой-то конкретной причине вы используете регулярное выражение? Вы пытались использовать XPath для этого? Вот несколько примеров использования XPath. http://www.w3schools.com/XPath/xpath_examples.asp

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...