2015-03-24 2 views
0

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

3*O#AA6160 F7 A7 P7 J7 R7 D7 I7 Y7 LHRMIA 1040 1455 * 744 0E 
     B7 H0 W0 K0 M0 L0 V0 G0 S0 Q0 N0 O0 

Пространства, которые вы видите во второй строке, по умолчанию. По существу, из этой строки я пытаюсь получить следующее:

$flightNumber = AA6160; 
$from = LHR; 
$to = MIA; 
$other = 1040 1455 * 744 0E; 
$seats = array(
    "F" => 7, 
    "A" => 7, 
    "P" => 7, 
    "J" => 7, 
    "R" => 7, 
    "D" => 7, 
    "I" => 7, 
    "Y" => 7, 
    "B" => 7, 
    "H" => 0, 
    "W" => 0, 
    "K" => 0, 
    "M" => 0, 
    "L" => 0, 
    "V" => 0, 
    "G" => 0, 
    "S" => 0, 
    "Q" => 0, 
    "O" => 0, 
) 

Правила следующие.
Начало строки начинается с цифры (в приведенном выше примере 3). Второй ряд является продолжением сидений из первого ряда. Если бы я опубликовал все данные, которые у меня есть, третья строка начинается с 4, что означает, что она не связана с двумя выше.

Номер рейса всегда начинается с буквы # и следит за двумя буквами и 1-4 номерами. Иногда между буквами и цифрами есть пробелы. Это все типы номеров полета я обнаружил

#AA6160 
#AA 57 
#BA 207 

Вторая строка будет содержать только продолжение мест, больше ничего. Это то, что я придумал до сих пор

while ($elNum < $elements->length) { 

    $flightInfo = $elements->item($elNum)->nodeValue; 

    if (preg_match('/^\\d/', $flightInfo) === 1) { 
     if(preg_match('/(\d)+[^#]*?\#(\p{Lu}{2})\s*(\d{1,4})\b\s*([\w. ]+?)(?=\s+\p{Lu}{6})\s([A-Z]{3})([A-Z]{3})(.+)/', $flightInfo, $matches)===1){ 
      $row = $matches[1]; 
      $fltcode = $matches[2].$matches[3]; 
      $ffrom = $matches[5]; 
      $fto = $matches[6]; 
      $other = $matches[7]; 

      $this->flights[$fltcode] = array(
       "command" => $terminal_command, 
       "row" => $row, 
       "flightNumber" => $fltcode, 
       "from" => $ffrom, 
       "to" => $fto, 
       "other" => $other 
      ); 
     } 
    } 
    ++$elNum; 
} 

Главное, с чем я борюсь, - это места. Я не уверен, как получить те, которые мне нужны из первой строки, и объединить их с теми из второй строки в формате вывода, в котором они нуждаются.

Я даже не уверен, что это лучшее предложение здесь, или если я должен взорвать все на пространствах и отсортировать их так?

Любые советы по ситуации оцениваются. Вот некоторые дополнительные данные

5*S#DL4386 J9 C9 D9 I9 Z9 W9 Y9 B9 LHRMIA 1235 1705 * 744 0E 
     M9 S9 H9 Q9 K9 L9 U9 T9 X9 V9 
6 #VS 5 J9 C9 D9 I9 Z9 W9 S9 H9 LHRMIA 1235 1705  744 0E 
     K9 Y9 B9 R9 L9 U9 M9 E9 Q9 X9 N9 O9 
7 #IB4637 F9 A9 J9 C9 D9 R9 I. W9 LHRMIA 1415 1825 * 744 0E 
     Z. Y9 B9 H9 K. M. L. V. S. N. Q. O. 

Благодарности

ответ

1

Пример, который использует XMLReader вместо DOMDocument для XML разбора, потому что это быстрее и использовать меньше памяти. Шаблоны спроектированы так, чтобы быть более читабельными (с режимом свободного пробега и названными захватами) и эффективными (с привязками, без бесполезных классов символов Юникода, таких как \p{Lu}, lookaheads или неиспользуемые группы захвата).

$xml = <<<EOD 
<?xml version="1.0" encoding="utf-8" ?> 
<root xmlns:terminal="http://test.com/terminal"> 
    <terminal:Text>1 #AY5767 F9 A9 P. J9 C9 D9 I9 Y9 LHRMIA 0945 1410 * 777 0E</terminal:Text> 
    <terminal:Text>  B9 H9 K9 M9 L9 V9 S9 N9 Q9 O9 G9 </terminal:Text> 

    <otherthings>blah blah blah</otherthings> 

    <terminal:Text>2 #AY5768 F9 A9 P. J9 C9 D9 I9 Y9 ROMMIL 0945 1410 * 777 0E</terminal:Text> 
    <terminal:Text>  B9 H9 K9 M9 L9 V9 S9 N9 Q9 O9 G9 </terminal:Text> 
    <terminal:Text>  E8 G8 R8 S8 T4 U2 </terminal:Text> 
</root> 
EOD; 

$patternFirstLine = <<<EOD 
~ 
\A 
    [0-9]+ \s+ 
    \# (?<code1> [A-Z]{2}) \s* (?<code2> [0-9]{1,4}) \s+ 
    (?<seat1> [A-Z][0-9.] (?: \s+ [A-Z][0-9.])*+) \s+ 
    (?<from> [A-Z]{3}) (?<to> [A-Z]{3}) \s+ 
    (?<other> .*\S) \s* 
\z 
~x 
EOD; 

$patternNextLines = <<<EOD 
~ 
\A \s* 
    (?<seatN> [A-Z][0-9.] (?: \s+ [A-Z][0-9.])*+) 
\s* \z 
~x 
EOD; 

$parser = new XMLReader(); 

$parser->xml($xml); 

$temp = false; 
$results = []; 

while($parser->read()) { 
    while ($parser->name === 'terminal:Text') { 
     if (preg_match($patternFirstLine, $parser->readInnerXML(), $m)) { 
      if ($temp) $results[] = $temp; 

      $temp = [ 
       "flightNumber" => $m['code1'] . $m['code2'], 
       "from"   => $m['from'], 
       "to"   => $m['to'], 
       "seats"  => $m['seat1'], 
       "other"  => $m['other'] 
      ]; 
     } elseif ($temp && preg_match($patternNextLines, $parser->readInnerXML(), $m)) 
      $temp['seats'] .= ' ' . $m['seatN']; 
     else 
      $temp = false; 

     $parser->next('Text'); 

    } 
} 

if ($temp) $results[] = $temp; 

$results = array_map(function ($i) { 
    $seats = explode(' ',$i['seats']); 
    $i['seats'] = []; 
    foreach ($seats as $seat) 
     $i['seats'][$seat[0]] = $seat[1]; 

    return $i; 
}, $results); 

print_r($results); 

Примечание: в этом примере, я использую XMLReader::xml() для загрузки содержимого XML, но один из главных интересов XMLReader является использование метода XMLReader::open с XML URI.

+0

Thats fantastic, просто перейдя через это сейчас, чтобы узнать его правильно. Одна вещь, которую я пытаюсь решить, - это. У меня есть переменная с именем $ responseData, которая в основном представляет собой строку, содержащую мои данные Soap (она должна быть сформирована XML). Как я могу загрузить это вместо этого? Я попытался использовать open, но он говорит, что не может открыть исходные данные. –

+0

Я не думаю, что вы можете использовать 'XMLReader :: open', так как вам нужно запросить сервис SOAP для получения ваших данных. Но вы всегда можете использовать 'XMLReader :: xml' с' $ responseData' –

+0

$ responseData уже содержит данные из Soap Service. Я попытался использовать его с XMLReader :: xml, но он возвращает пустой массив. –

1

Вы могли бы попробовать что-то более простое, но я не уверен на 100%, что это охватывает все, что вам нужно.

function yourFunction($input) { 
    // get the individual words, meaning split on whitespace 
    $words = preg_split('/\s+/', $input); 
    // filter the words the best we can 
    $valuableInput = array_filter($words, function($word) { 
     $chars = str_split($word); 
     return count($chars) == 2 && is_int($chars[1]); 
    }); 

    // Create the mapping between the characters and the numbers 
    $output = array(); 
    foreach ($valuableInput as $word) { 
     $chars = str_split($word); 
     $output[$chars[0]] = $chars[1]; 
    } 
    return $output; 
} 
Смежные вопросы