Проблема регулярного выражения с необязательной фразой в разных форматах

У меня есть файл, из которого я хочу разобрать конкретные значения. Как собрать все три из следующих регулярных выражений вместе, чтобы получить единую группу записей для каждого теста, независимо от того, имеет ли он измерения или нет, и содержит ли он ошибки И включает ли измерения и ошибки, если они есть? Может быть любое количество тестов, любое количество мер в тесте, но одна ошибка в тесте без других мер. Я пробовал много разных комбинаций без успеха. Я полагаю, что мне нужно использовать прогнозирование и чередование, но не нашел правильную комбинацию. К вашему сведению, регулярное выражение хранится в БД и используется приложением C#. Заранее спасибо!

Входной файл:

<event>
<common>
    <event_start_time>2014-01-29T17:30:36</event_start_time>
    <operator>10586546</operator>
    <shift>A</shift>
    <program>PPM</program>
    <program_revision>eo01</program_revision>
</common>
<test_instance>
<teststart startid = "ABCDEF">
        <test>MB</test>
        <test_start_time>2014-01-29T17:30:39</test_start_time>
        <exe>HelloWorld</exe>
        <subtest>CheckVersion</subtest>
        <subtest_number>1</subtest_number>
    </teststart>
    <testend endid = "ABCDEF">
        <test_result>PASS</test_result>
        <test_duration duration_units="millisec">1000</test_duration>
    </testend>
    <teststart startid = "CDEFG">
        <test>MB</test>
        <test_start_time>2014-01-29T17:30:40</test_start_time>
        <exe>HelloWorld</exe>
        <subtest>Program1</subtest>
        <subtest_number>2</subtest_number>
    </teststart>
    <measurement measid = "CDEFG">
        <measurement_name>CycleCounter </measurement_name>
        <numeric_measurement> 1</numeric_measurement>
        <measurement_time>2014-01-29T17:30:50</measurement_time>
    </measurement>
    <measurement measid = "CDEFG">
        <measurement_name>Counter </measurement_name>
        <numeric_measurement> 1</numeric_measurement>
        <measurement_time>2014-01-29T17:30:50</measurement_time>
    </measurement>
    <testend endid = "CDEFG">
        <test_result>PASS</test_result>
        <test_duration duration_units="millisec">10000</test_duration>
    </testend>
    <teststart startid = "xYZABC">
        <test>MB</test>
        <test_start_time>2014-01-29T17:36:01</test_start_time>
        <exe>HelloWorld</exe>
        <subtest>Check2</subtest>
        <subtest_number>17</subtest_number>
    </teststart>
    <measurement measid = "xYZABC">
        <measurement_name>ERROR1</measurement_name>
        <error_code>31001717</error_code>
        <error_message>MB:FAILED_CHECK_TEST</error_message>
        <measurement_time>2014-01-29T17:36:50</measurement_time>
        <measurement_result>FAIL</measurement_result>
    </measurement>
    <testend endid = "xYZABC">
        <test_result>FAIL</test_result>
        <test_duration duration_units="millisec">49000</test_duration>
    </testend>
</test_instance>
<event_duration duration_units="sec">374</event_duration>
<event_result>FAIL</event_result>

Для разбора тестовой части я использую регулярное выражение, которое работает:

\<teststart\sstartid\s=\s"
(?<tid>.*?)"\>
.*\n
.*\<test\>
(?<testid>.*?)\<
.*\n
.*\<test_start_time\>
(?<teststartdate>.*?)T
(?<teststarttime>.*?)\</.*\n
.*?
\<exe\>
(?<texe>.*?)\<.*\n
(.*?\n)*?
.*?\<testend.*?\n
.*?\<test_result\>
(?<result>.*?)\<.*\n
.*?duration_units="
(?<dunits>.{1}).*?
\>
(?<duration>.*?)\<

Для разбора данных измерений я использую регулярное выражение, которое работает:

.*?\<measurement\smeasid\s=\s"
(?<measid>.*?)"\>.*\r\n
(.*?\r\n)*?
.*?
\<measurement_name\>
(?<measurename>.*?)\<.*\r\n
.*?
\<numeric_measurement\>
(?<measurenum>[^/s].*?)\<.*\r\n
.*?
\<measurement_time\>
(?<measureDate>[^/s].*?)T
(?<measureTime>[^/s].*?)\<.*\r\n

Для анализа ошибки я использую регулярное выражение, которое работает:

.*?\<measurement\smeasid\s=\s"
(?<measid>.*?)"\>.*\r\n
.*?\<measurement_name\>
(?<measurename>.*?)\<.*\r\n
.*?\<error_code\>
(?<sterrcode>.*?)\<.*\r\n
.*?\<error_message\>
(?<sterrmsg>.*?)\<.*\r\n
.*?\<measurement_time\>
(?<measureDate>[^/s].*?)T
(?<measureTime>[^/s].*?)\<.*\r\n
.*?\<measurement_result\>
(?<measureResult>[^/s].*?)\<.*\r\n

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Да, я знаю, что вводом является XML, но я не могу изменить приложение для десериализации, оно использует регулярные выражения.

1 ответ

Вы можете использовать обратные ссылки из утверждений нулевой ширины.

(?=.*?(?<foo>a))?(?=.*?(?<bar>b))?

применительно к любому из

ab
ba

сообщит

group "foo" = "a"
group "bar" = "b"

и применительно к

a

это сообщит

group "foo" = "a"
group "bar" = (does not exist)

и наоборот.

Другие вопросы по тегам