PHP SimpleXML XPath содержит () для поиска других элементов, на которые ссылается этот элемент - PullRequest
1 голос
/ 13 ноября 2009

Мне дают XML в следующем формате, и я анализирую его с помощью PHP SimpleXML.

<?xml version="1.0" encoding="UTF-8"?>
<ManageMyBooking>
    <BookingInfo>
        <PartyDetails>
            <Passenger>
                <PaxNo>1</PaxNo>
                <Title>Mrs</Title>
                <Surname>Murphy</Surname>
            </Passenger>
            <Passenger>
                <PaxNo>2</PaxNo>
                <Title>Mr</Title>
                <Surname>Murphy</Surname>
            </Passenger>
            <Passenger>
                <PaxNo>3</PaxNo>
                <Title>Miss</Title>
                <Surname>Murphy</Surname>
            </Passenger>
        </PartyDetails>
        <Accommodation>
            <Units>
                <Unit>
                    <UnitNo>1</UnitNo>
                    <UnitDesc>...</UnitDesc>
                    <PaxAssociated>1|2</PaxAssociated>
                </Unit>
                <Unit>
                    <UnitNo>2</UnitNo>
                    <UnitDesc>...</UnitDesc>
                    <PaxAssociated>3</PaxAssociated>
                </Unit>
            </Units>
        </Accommodation>
    </BookingInfo>
</ManageMyBooking>

Я перебираю Единицы (Комнаты) таким образом:

// $Accommodation is a SimpleXML Object defined earlier, and able to provide relevant info
<?  foreach ($Accommodation->Units as $Units) {
        foreach ($Units->Unit as $Unit) {
        // (room/unit details echoed out here)
            foreach ($Unit->xpath('//Passenger[contains(PaxAssociated,./PaxNo)]') as $RoomPax) { ?>
<?= $RoomPax->Title $RoomPax->Surname" ?><br />
<?= "$RoomPax->Title $RoomPax->Surname" ?><br />
<?          }
        }
    } ?>

в попытке показать имена пассажиров (Пакс) в каждой комнате.

Но этот xpath никого не находит, а следующий получает всех.

//Passenger[contains(PaxNo,./PaxAssociated)]

Что особенно расстраивает, так это то, что я успешно использовал XPath в другом месте того же PHP для очень похожей цели, без проблем.

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


Edit: для полноты и ответить на вопрос нескольких людей: Следующее работает в других местах кода (но не на 100% правильно, учитывая возможное совпадение «22» против «2».

//Flight[contains(PaxAssociated,./PaxNo)]

1 Ответ

3 голосов
/ 13 ноября 2009

Это:

//Passenger[contains(PaxNo,./PaxAssociated)]

is: Найти любого <Passenger> с дочерним элементом <PaxNo>, значение которого содержит значение дочернего элемента <PaxAssociated>. Это будет работать только с такой структурой данных (которой у вас явно нет):

<ManageMyBooking>
  <BookingInfo>
    <PartyDetails>
      <Passenger>
        <PaxNo>1|2</PaxNo>  <!-- note the exchanged value! -->
        <PaxAssociated>1</PaxAssociated>
      </Passenger>
    </PartyDetails>
  </BookingInfo>
</ManageMyBooking>

Так что это неправильно для нескольких учетных записей. Что вы имеете в виду , вероятно, является динамическим выражением XPath, например:

foreach ($Units->Unit as $Unit) {
  $XPath = "//Passenger[contains('". $Unit->PaxAssociated . "', PaxNo)]";
  foreach ($Unit->xpath($XPath) as $RoomPax) {
    // ...
  }
}

Это работает на первый взгляд, но не является отказоустойчивым, потому что "22" также содержит "2". Таким образом, выполнение только contains() не даст вам нигде . Правильно будет:

$XPath = "//Passenger[contains('|". $Unit->PaxAssociated ."|', concat('|', PaxNo, '|'))]";

Таким образом, вы проверяете "| 22 |" против "| 2 |", что вернет false.

...