как проверить xml файл построчно с помощью скрипта perl - PullRequest
1 голос
/ 29 апреля 2020

Я хотел бы сравнить два файла: один - текстовый файл входного файла пользователя, а другой файл - файл конфигурации, который является xml файлом. если значение входного файла пользователя совпадает с конфигурационным файлом, то показать соответствующую функцию.

это входной файл пользователя

L84A:FIP:70:155:15:18:
L83A:55FIP:70:155:15:

В приведенном выше файле: L84A - это Design_ID, FIP - это Process_ID и 70 18 - это register_ID.

это конфигурационный файл

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Sigma>
        <Run>
                <DESIGN_ID>L83A</DESIGN_ID>
                <PROCESS_ID>55FIP</PROCESS_ID>
                <RegisterList>
                        <Register>70</Register>
                        <Register>155</Register>
                </RegisterList>
        </Run>
        <Run>
                <DESIGN_ID>L83A</DESIGN_ID>
                <PROCESS_ID>FRP</PROCESS_ID>
                <RegisterList>
                        <Register>141</Register>
                        <Register>149</Register>
                        <Register>151</Register>
                </RegisterList>
        </Run>
        <Run>
                <DESIGN_ID>L84A</DESIGN_ID>
                <PROCESS_ID>55FIP</PROCESS_ID>
                <RegisterList>
                        <Register>70</Register>
                        <Register>155</Register>
                </RegisterList>
        </Run>
</Sigma>

, поэтому в этом случае вывод должен показать:

L84A: doesn't has FIP process ID in config file.
L83A:
  55FIP
   70 - existing register ID
   155 - existing register ID
   15 - no existing register ID.

мой код не проверяет соответствующий идентификатор процесса и зарегистрируйте идентификатор. Это показано ниже.

L84A
 FIP
  70 - existing register ID
  155 - existing register ID
  15 - existing register ID
  18 - no existing register ID
L83A
 55FIP
  70 - existing register ID
  155 - existing register ID
  15 - existing register ID

ниже мой код:

use strict; 
use warnings;
use vars qw($file1 $file1cnt @output);
use XML::Simple;
use Data::Dumper;
# create object
my $xml = new XML::Simple;

# read XML file
my $data = $xml->XMLin("sigma_loader.xml");
my $file1 = "userinput.txt";

readFileinString($file1, \$file1cnt); 

while($file1cnt=~m/^((\w){4})\:([^\n]+)$/mig)
{  
  my $DID = $1;
  my $reqconfig = $3;
  while($reqconfig=~m/^((\w){5})\:([^\n]+)$/mig) #Each line from user request
  {  
    my $example1 = $1; #check for FPP/QBPP process
    my $example2 = $3; #display bin full lists.

   if(Dumper($data) =~ $DID)
   {
     print"$DID\n";
     if(Dumper($data) =~ $example1)
     {
       print"$example1\n";
       my @second_values = split /\:/, $example2;
       foreach my $sngletter(@second_values)
        { 

          if( Dumper($data) =~ $sngletter)
          {
            print"$sngletter - existing register ID\n";
          }
          else
          {
            print"$sngletter - no existing register ID\n";
          }
        }
     }
     else
     {
      print"$DID doesn't has $example1 process ID in config file\n";
     }
   }
   else
   {
    print"new Design ID deteced\n";
   } 
 }
 while($reqconfig=~m/^((\w){3})\:([^\n]+)$/mig) #Each line from user request
 {  
    my $example1 = $1; #check for FPP/QBPP process
    my $example2 = $3; #display bin full lists.

   if(Dumper($data) =~ $DID)
   {
     print"$DID\n";
     if(Dumper($data) =~ $example1)
     {
       print"$example1\n";
       my @second_values = split /\:/, $example2;
       foreach my $sngletter(@second_values)
        { 

          if( Dumper($data) =~ $sngletter)
          {
            print"$sngletter - existing register ID\n";
          }
          else
          {
            print"$sngletter - no existing register ID\n";
          }
        }
     }
     else
     {
      print"$DID doesn't has $example1 process ID in config file\n";
     }
   }
   else
   {
    print"new Design ID deteced\n";
   } 
 }
}

sub readFileinString
#------------------>
{
    my $File = shift;
    my $string = shift;
    use File::Basename;
    my $filenames = basename($File);
    open(FILE1, "<$File") or die "\nFailed Reading File: [$File]\n\tReason: $!";
    read(FILE1, $$string, -s $File, 0);
    close(FILE1);
} 

1 Ответ

2 голосов
/ 29 апреля 2020

В вашем коде есть пара вещей, которые на самом деле не имеют смысла, например, использование Data :: Dumper и синтаксический анализ вывода с помощью регулярного выражения. Я не собираюсь проверять ваш код, так как он не является верным c в переполнении стека, но вместо этого я дам вам альтернативное решение и проведу вас через него.

Обратите внимание, что XML: : Простой не великий инструмент. Его использование не рекомендуется, потому что оно плохо работает с определенными случаями. Но для вашей очень простой структуры XML она будет работать, поэтому я сохранил ее.

use strict;
use warnings;
use XML::Simple;
use feature 'say';

# read XML file and reorganise it for easier use
my $data;
foreach my $run (@{XMLin(\*DATA)->{Run}}) {
    $data->{$run->{DESIGN_ID}}->{$run->{PROCESS_ID}} =
      {map { $_ => 1 } @{$run->{RegisterList}->{Register}}};
}

# read the text file - I've skipped the read
my @user_input = qw(
  L84A:FIP:70:155:15:18:
  L83A:55FIP:70:155:15:
);

foreach my $line (@user_input) {
    chomp $line
      ; # we don't need this in my example, but you do when you read from a file
    my ($design_id, $process_id, @register_ids) = split /:/, $line;

    # extra error checking just in case
    if (not exists $data->{$design_id}) {
        say "$design_id does't exist in data";
        next;
    }
    if (not exists $data->{$design_id}->{$process_id}) {
        say "$design_id: doesn't have $process_id";
        next;
    }

    say "$design_id:";
    say " $process_id";
    foreach my $register_id (@register_ids) {
        if (exists $data->{$design_id}->{$process_id}->{$register_id}) {
            say "  $register_id - existing register ID";
        }
        else {
            say "  $register_id - no existing register ID";
        }
    }
}


__DATA__
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Sigma>
        <Run>
                <DESIGN_ID>L83A</DESIGN_ID>
                <PROCESS_ID>55FIP</PROCESS_ID>
                <RegisterList>
                        <Register>70</Register>
                        <Register>155</Register>
                </RegisterList>
        </Run>
        <Run>
                <DESIGN_ID>L83A</DESIGN_ID>
                <PROCESS_ID>FRP</PROCESS_ID>
                <RegisterList>
                        <Register>141</Register>
                        <Register>149</Register>
                        <Register>151</Register>
                </RegisterList>
        </Run>
        <Run>
                <DESIGN_ID>L84A</DESIGN_ID>
                <PROCESS_ID>55FIP</PROCESS_ID>
                <RegisterList>
                        <Register>70</Register>
                        <Register>155</Register>
                </RegisterList>
        </Run>
</Sigma>

Я сделал несколько предположений.

  1. Вы уже знаете, как читать текстовый файл, поэтому я вставил его в массив построчно. Однако у вашего кода чтения файлов есть некоторые проблемы, вы должны использовать трехэлементные открытые и лексические дескрипторы файлов. Ваш вызов open должен выглядеть следующим образом:

    open my $fh, '<', $filename or die "$!: error...";
    

    В качестве альтернативы рассмотрите возможность использования Path :: Tiny .

  2. I'm взять файл XML из раздела __DATA__. Это похоже на файловый дескриптор.

Итак, давайте посмотрим на мой код.

Когда мы читаем структуру XML, она выглядит прямо из XMLin .

\ {
    Run   [
        [0] {
            DESIGN_ID      "L83A",
            PROCESS_ID     "55FIP",
            RegisterList   {
                Register   [
                    [0] 70,
                    [1] 155
                ]
            }
        },
        [1] {
            DESIGN_ID      "L83A",
            PROCESS_ID     "FRP",
            RegisterList   {
                Register   [
                    [0] 141,
                    [1] 149,
                    [2] 151
                ]
            }
        },
        [2] {
            DESIGN_ID      "L84A",
            PROCESS_ID     "55FIP",
            RegisterList   {
                Register   [
                    [0] 70,
                    [1] 155
                ]
            }
        }
    ]
}

Это не очень полезно для того, что мы планируем делать, поэтому мы должны изменить его. Я хочу использовать exists для ссылок ha sh позже, чтобы упростить поиск, если есть совпадения для идентификаторов, которые мы ищем. Это называется lookup ha sh. Мы можем пропустить ключ ->{Run}, так как XML :: Simple объединяет все элементы <Run> в ссылку на массив, а тег <Sigma> просто пропускается, потому что это элемент root.

Каждый идентификатор дизайна может иметь несколько процессов, поэтому мы организуем эти два иерархически, и мы помещаем в другой поиск ha sh, где каждый регистр является ключом, а мы просто используем 1 в качестве ключа. Ключ не имеет значения.

Это дает нам другую структуру данных:

\ {
    L83A   {
        55FIP   {
            70    1,
            155   1
        },
        FRP     {
            141   1,
            149   1,
            151   1
        }
    },
    L84A   {
        55FIP   {
            70    1,
            155   1
        }
    }
}

Это намного легче понять и использовать позже.

Теперь мы анализируем пользователя ввод и итерации по каждой строке. Формат кажется понятным. Это немного похоже на файл CSV, но с использованием двоеточий :, поэтому мы можем split. Это дает нам два идентификатора, и все последующие значения являются регистрами, поэтому мы помещаем их в массив.

В вашем примере нет случая, когда идентификатор проекта не существует в файле XML, но учитывая, что это основано на пользовательском вводе, мы должны все равно проверить. В реальном мире данные всегда грязные.

Затем мы можем проверить, находится ли $process_id exists внутри $design_id в наших данных. Если это не так, мы сообщаем пользователю и переходим к строке next.

Затем мы должны выполнить итерацию всех идентификаторов регистра. Либо $register_id существует в нашем втором поиске ha sh, либо его нет.

Это дает нам точный вывод, который вы ожидаете.

L84A: doesn't have FIP
L83A:
 55FIP
  70 - existing register ID
  155 - existing register ID
  15 - no existing register ID

Этот код намного короче, его легче читать и он работает быстрее. Я использовал Data :: Printer , чтобы показать структуры данных.

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