2015-07-24 7 views
1

Я пытаюсь найти регулярное выражение, которое может вывести значение из строки, которая отформатирована как XML, но находится внутри тега CDATA. Строка выглядит так:Regex для захвата значения в узле XML.

<OAORNO>1234546qwerty</OAORNO><OBITNO>12345-qwerty</OBITNO><OBITDS>123456 qwerty</OBITDS> 

Значения могут быть цифрами, символами слов, специальными символами и пробелами. Или любая их комбинация. Поэтому мне нужен один размер, соответствующий всем шаблонам.

У меня есть сплит-преобразователь строк, который принимает регулярные выражения в качестве параметра. Конвертер разделит sting на основе параметра, который вы его подаете, и верните строку в виде массива. Который я буду отображать в виде списка.

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

Ближайшая модель я придумал это:

(?<=\>)(.+)(?=\<) 

Но это захватывает все между первыми и последними узлами. Так как в примере выше она захватывает все между и так вы в конечном итоге с:

1234546qwerty</OAORNO><OBITNO>12345-qwerty</OBITNO><OBITDS>123456 qwerty 

Там должен быть способ сделать это, любая помощь будет оценен по достоинству!

+0

Вы не можете abritrary XML надежно с Regex. Есть ли причина, по которой вы не можете использовать стандартный синтаксический анализатор XML? – Mitch

+0

В среде, в которой я работаю, есть ограничения, которые мешают мне использовать код позади. – EMAW2008

+0

Вы можете получить доступ к синтаксическим анализаторам XML в большинстве шаблонов, или вы можете сделать это на стороне клиента. Если у вас есть регулярное выражение, вы должны иметь возможность использовать правильный синтаксический анализатор XML. Какие рамки вы используете? – Mitch

ответ

0

Как и ваш конвертер Regex, вы можете использовать конвертер для XML-фрагмента и преобразовать его в XElement. Это позволит вам bind to the XML Document:

<Grid.Resources> 
    <local:XmlFragmentConverter x:Key="xElementConverter" /> 
</Grid.Resources> 
<TextBox x:Name="xmlTb" Text="&lt;OAORNO&gt;1234546qwerty&lt;/OAORNO&gt;&lt;OBITNO&gt;12345-qwerty&lt;/OBITNO&gt;&lt;OBITDS&gt;123456 qwerty&lt;/OBITDS&gt;" Margin="10,10,322,286" Height="23" /> 

<ListBox HorizontalAlignment="Left" Height="100" Margin="10,38,0,0" VerticalAlignment="Top" Width="185" 
      DataContext="{Binding ElementName=xmlTb, Path=Text, Converter={StaticResource xElementConverter}}" 
      ItemsSource="{Binding Path=Elements}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock> 
       <Run Text="{Binding Path=Name,Mode=OneWay}" /><Run Text=": "/><Run Text="{Binding Path=Value, Mode=OneWay}" /> 
      </TextBlock> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 
<ListBox HorizontalAlignment="Left" Height="100" Margin="10,143,0,0" VerticalAlignment="Top" Width="185" 
    DataContext="{Binding Text, Converter={StaticResource xElementConverter}, ElementName=xmlTb}" 
    ItemsSource="{Binding Elements[OBITNO]}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock><Run Text="{Binding Name, Mode=OneWay}" /><Run Text=": "/><Run Text="{Binding Value, Mode=OneWay}" /></TextBlock> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Производит:

Demo showing a binding to the xml data

Преобразователь:

sealed class XmlFragmentConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
     { 
      return null; 
     } 

     var xmlString = value as string; 
     if (string.IsNullOrWhiteSpace(xmlString)) 
     { 
      throw new ArgumentException("value must be a string containing xml data", "value"); 
     } 

     return XDocument.Parse("<root>" + xmlString + "</root>").Root; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
+0

спасибо. это было лучшее решение. – EMAW2008

1

+ по умолчанию является жадным, что означает, что он будет захватывать как можно больше. Вы можете сделать это не жадным, чтобы он зафиксировал кратчайшее совпадение, добавив ? после него, например: (?<=\>)(.+?)(?=\<)

Однако есть еще одна проблема с вашим шаблоном. .+? будет соответствовать любому, включая немедленный символ <, поэтому, когда в элементе нет текста, он захватывает слишком много. Что-то вроде (?<=\>)([^<]+?)(?=\<) было бы лучше в этом случае.

Смежные вопросы