2013-03-18 1 views
0

Я работаю над XML-документом, мне нужно его открыть и преобразовать в верхний регистр некоторые определенные значения тегов в одной строке. Если у меня есть то же самое слово, которое он делает только замену одного из них, хотя я использую две разные, если петли: Это мой XML:Как я могу сделать замены одного и того же слова в Perl на одной и той же строке xml?

<pageID="1" width="827" height="1169" Sender_Company="société" Sender_Address="société" Sender_Fax="" Category="C2" Language_2="" Document_Object="" Language_1="french" Language_3="" NumPage="1" Script_1="typed"> 

Это мой код:

while (<FILEIN>) { 
    if ($_ =~ /pageID="1"/) { 
     $haschanged = 1; 
     if ($_ !~ /Sender_Address=""/) { 
      if ($_ =~ /(Sender_Address="(.*?)")/){ 
       my $SenderAddress = $2; 
       $SenderAddress = uc($SenderAddress); 
       $_ =~ s/$1/Sender_Address="$SenderAddress"/; 
      } 
     } 

     if ($_ !~ /Sender_Company=""/) { 
      if ($_ =~ /(Sender_Company="(.*?)")/) { 
       my $SenderCompany = $2; 
       $SenderCompany = uc($SenderCompany); 
       $_ =~ s/$1/Sender_Company="$SenderCompany"/; 
       #print "$_\n"; 
      } 
     } 
    } 
} 

Когда я использую два разных значения для Sender_Company="bla" и Sender_Address="société", преобразование в верхний регистр работает, но когда я использую в этом случае одно и то же слово Sender_Company="société" и Sender_Address="société", он не выполняет преобразование в верхний регистр. У кого-нибудь есть идеи? Я не могу найти логику, за которой он не хочет преобразовать одно и то же слово, когда я использую два разных цикла if за один раз. Спасибо!

+0

Благодаря отступу вашего кода. Это поможет вам найти проблемы в целом, и это немного уважает читателей, когда вы обращаетесь за помощью. –

+0

Он отлично работает для меня. – Toto

+2

Используйте XML-синтаксический анализатор для управления XML. – Mat

ответ

2

Ваше понимание XML немного спорно:

  1. Это не XML. Это фрагмент XML в большинстве (Элемент не закрыт, имя тега не может удвоить, как атрибут, как <pageID="1">, не <?xml ...?> декларации, ни корневого элемента, ...)
  2. Не разобрать XML с регулярными выражениями ;-)
  3. XML не имеет понятия «линии».

Кроме того, код должен работать нормально. Обратите внимание, что вы можете сделать вашу жизнь проще, и ваш код короче:

  1. $_ =~ /foo/ таким же, как /foo/, $_ !~ /foo/ таких же, как !/foo/.
  2. Вместо извлечения двух захватов, и подставляя результат во втором регулярном выражении, вы можете сделать все это за один шаг:

    s{ (?<=Sender_Address=") ([^"]+) (?=") }{ uc $1 }ex 
    

    Подождите, что? Я извлекаю один или несколько не-символов, которым предшествует строка Sender_Address=", а за ними следует " (соображения обхода). То, что происходит между мной, и подставлять его в верхнюю версию. Поскольку я сопоставляю хотя бы один характер, не должен испытать для пустого случая тега. флаг /e позволяет код в замене (на самом деле не здесь необходимые), а /x позволяет включить nonmatching пробелов для лучшего форматирования.

    Вы можете легко расширить это для обоих атрибутов вы хотите прописные:

    # This subsumes your whole logic inside `if (/pageID="1"/)` 
    $haschanged = 1; 
    for my $attr (qw/Sender_Address Sender_Company/) { 
        s{ (?<=\Q$attr\E=") ([^"]+) (?=") }{ uc $1 }ex; 
    } 
    

    \Q...\E вызывает Интерполом чтобы соответствовать буквально, даже если он содержит символы, которые в противном случае были бы метасимволами регулярных выражений.

Есть несколько оставшихся ошибок:

  1. Вы не прописные символы, которые даны в качестве субъектов.
  2. XML допускает одинарные кавычки '...' для использования в качестве разделителей значений тегов.Вы не обрабатывать их
  3. Смотрите пункты под Ваше понимание XML ...

Все они могут быть решены с помощью XML-анализатор, а затем преобразуя атрибуты в DOM.