скопировать часть XML в PHP - PullRequest
1 голос
/ 10 ноября 2019

Я пытаюсь извлечь часть из существующего содержимого XML. Например: я хочу извлечь весь блок <air:AirPricingSolution> ..... </air:AirPricingSolution> из данного xml. мой xml выглядит так:

        <air:LowFareSearchRsp xmlns:air="http://www.travelport.com/schema/air_v48_0" TraceId="trace" TransactionId="5C13B61C0A076478D128A37655BD80F6" ResponseTime="3150" DistanceUnits="MI" CurrencyType="BDT">
            <air:AirPricingSolution Key="lR26Z14R2BKAVzCGAAAAAA==" TotalPrice="BDT53498" BasePrice="USD444.00" ApproximateTotalPrice="BDT53498" ApproximateBasePrice="BDT37186" EquivalentBasePrice="BDT37186" Taxes="BDT16312" ApproximateTaxes="BDT16312">
                <air:Journey TravelTime="P0DT4H10M0S">
                  <air:AirSegmentRef Key="lR26Z14R2BKAWzCGAAAAAA=="/>
                </air:Journey>
                <air:Journey TravelTime="P0DT4H0M0S">
                  <air:AirSegmentRef Key="lR26Z14R2BKAYzCGAAAAAA=="/>
                </air:Journey>
                <air:LegRef Key="lR26Z14R2BKAazCGAAAAAA=="/>
                <air:LegRef Key="lR26Z14R2BKAbzCGAAAAAA=="/>
                <air:AirPricingInfo Key="lR26Z14R2BKAczCGAAAAAA==" TotalPrice="BDT26749" BasePrice="USD222.00" ApproximateTotalPrice="BDT26749" ApproximateBasePrice="BDT18593" EquivalentBasePrice="BDT18593" Taxes="BDT8156" ApproximateTaxes="BDT8156" LatestTicketingTime="2020-01-06" PricingMethod="Guaranteed" ETicketability="Yes" PlatingCarrier="MH" ProviderCode="1G" Cat35Indicator="false">
                  <air:FareInfoRef Key="lR26Z14R2BKAlzCGAAAAAA=="/>
                  <air:FareInfoRef Key="lR26Z14R2BKA0zCGAAAAAA=="/>
                  <air:BookingInfo BookingCode="N" BookingCount="9" CabinClass="Economy" FareInfoRef="lR26Z14R2BKAlzCGAAAAAA==" SegmentRef="lR26Z14R2BKAWzCGAAAAAA=="/>
                  <air:BookingInfo BookingCode="N" BookingCount="9" CabinClass="Economy" FareInfoRef="lR26Z14R2BKA0zCGAAAAAA==" SegmentRef="lR26Z14R2BKAYzCGAAAAAA=="/>
                  <air:TaxInfo Category="BD" Amount="BDT500" Key="lR26Z14R2BKAdzCGAAAAAAAA"/>
                  <air:TaxInfo Category="E5" Amount="BDT75" Key="lR26Z14R2BKAezCGAAAAAAAA"/>
                  <air:TaxInfo Category="OW" Amount="BDT2000" Key="lR26Z14R2BKAfzCGAAAAAAAA"/>
                  <air:TaxInfo Category="UT" Amount="BDT3000" Key="lR26Z14R2BKAgzCGAAAAAAAA"/>
                  <air:TaxInfo Category="G1" Amount="BDT407" Key="lR26Z14R2BKAhzCGAAAAAAAA"/>
                  <air:TaxInfo Category="H8" Amount="BDT21" Key="lR26Z14R2BKAizCGAAAAAAAA"/>
                  <air:TaxInfo Category="MY" Amount="BDT1483" Key="lR26Z14R2BKAjzCGAAAAAAAA"/>
                  <air:TaxInfo Category="YQ" Amount="BDT670" Key="lR26Z14R2BKAkzCGAAAAAAAA"/>
                  <air:FareCalc>DAC MH KUL 111.00NBC6MSBD MH DAC 111.00NBC6MSBD NUC222.00END ROE1.0</air:FareCalc>
                  <air:PassengerType Code="ADT"/>
                  <air:PassengerType Code="ADT"/>
                  <air:ChangePenalty PenaltyApplies="Anytime">
                    <air:Amount>BDT3350.0</air:Amount>
                  </air:ChangePenalty>
                  <air:CancelPenalty NoShow="true" PenaltyApplies="Anytime">
                    <air:Percentage>100.00</air:Percentage>
                  </air:CancelPenalty>
                </air:AirPricingInfo>
              </air:AirPricingSolution>
    <air:AirPricingSolution ........>
    ........
    </air:AirPricingSolution>
        </air:LowFareSearchRsp>

Я пытался так:

foreach($Results->children('air',true) as $nodes){
    foreach($nodes->children('air',true) as $hsr){
        if(strcmp($hsr->getName(),'AirPricingSolution') == 0){
            foreach($hsr->children("air",true) as $child){
                echo $child->asXML();
            }
        }
    }
}

, но он просто показывает мне значения внутри узлов xml ... но я хочу весь блокxml как есть.

Ответы [ 2 ]

1 голос
/ 10 ноября 2019

Используя стандартные DOMDocument и DOMXpath, довольно просто извлечь (клонировать) части документа, которые можно использовать позже, по вашему желанию.

$xml='<?xml version="1.0" encoding="UTF-8"?>
    <air:LowFareSearchRsp xmlns:air="http://www.travelport.com/schema/air_v48_0" TraceId="trace" TransactionId="5C13B61C0A076478D128A37655BD80F6" ResponseTime="3150" DistanceUnits="MI" CurrencyType="BDT">

        <air:AirPricingSolution Key="lR26Z14R2BKAVzCGAAAAAA==" TotalPrice="BDT53498" BasePrice="USD444.00" ApproximateTotalPrice="BDT53498" ApproximateBasePrice="BDT37186" EquivalentBasePrice="BDT37186" Taxes="BDT16312" ApproximateTaxes="BDT16312">
            <air:Journey TravelTime="P0DT4H10M0S">
              <air:AirSegmentRef Key="lR26Z14R2BKAWzCGAAAAAA=="/>
            </air:Journey>
            <air:Journey TravelTime="P0DT4H0M0S">
              <air:AirSegmentRef Key="lR26Z14R2BKAYzCGAAAAAA=="/>
            </air:Journey>
            <air:LegRef Key="lR26Z14R2BKAazCGAAAAAA=="/>
            <air:LegRef Key="lR26Z14R2BKAbzCGAAAAAA=="/>
            <air:AirPricingInfo Key="lR26Z14R2BKAczCGAAAAAA==" TotalPrice="BDT26749" BasePrice="USD222.00" ApproximateTotalPrice="BDT26749" ApproximateBasePrice="BDT18593" EquivalentBasePrice="BDT18593" Taxes="BDT8156" ApproximateTaxes="BDT8156" LatestTicketingTime="2020-01-06" PricingMethod="Guaranteed" ETicketability="Yes" PlatingCarrier="MH" ProviderCode="1G" Cat35Indicator="false">
              <air:FareInfoRef Key="lR26Z14R2BKAlzCGAAAAAA=="/>
              <air:FareInfoRef Key="lR26Z14R2BKA0zCGAAAAAA=="/>
              <air:BookingInfo BookingCode="N" BookingCount="9" CabinClass="Economy" FareInfoRef="lR26Z14R2BKAlzCGAAAAAA==" SegmentRef="lR26Z14R2BKAWzCGAAAAAA=="/>
              <air:BookingInfo BookingCode="N" BookingCount="9" CabinClass="Economy" FareInfoRef="lR26Z14R2BKA0zCGAAAAAA==" SegmentRef="lR26Z14R2BKAYzCGAAAAAA=="/>
              <air:TaxInfo Category="BD" Amount="BDT500" Key="lR26Z14R2BKAdzCGAAAAAAAA"/>
              <air:TaxInfo Category="E5" Amount="BDT75" Key="lR26Z14R2BKAezCGAAAAAAAA"/>
              <air:TaxInfo Category="OW" Amount="BDT2000" Key="lR26Z14R2BKAfzCGAAAAAAAA"/>
              <air:TaxInfo Category="UT" Amount="BDT3000" Key="lR26Z14R2BKAgzCGAAAAAAAA"/>
              <air:TaxInfo Category="G1" Amount="BDT407" Key="lR26Z14R2BKAhzCGAAAAAAAA"/>
              <air:TaxInfo Category="H8" Amount="BDT21" Key="lR26Z14R2BKAizCGAAAAAAAA"/>
              <air:TaxInfo Category="MY" Amount="BDT1483" Key="lR26Z14R2BKAjzCGAAAAAAAA"/>
              <air:TaxInfo Category="YQ" Amount="BDT670" Key="lR26Z14R2BKAkzCGAAAAAAAA"/>
              <air:FareCalc>DAC MH KUL 111.00NBC6MSBD MH DAC 111.00NBC6MSBD NUC222.00END ROE1.0</air:FareCalc>
              <air:PassengerType Code="ADT"/>
              <air:PassengerType Code="ADT"/>
              <air:ChangePenalty PenaltyApplies="Anytime">
                <air:Amount>BDT3350.0</air:Amount>
              </air:ChangePenalty>
              <air:CancelPenalty NoShow="true" PenaltyApplies="Anytime">
                <air:Percentage>100.00</air:Percentage>
              </air:CancelPenalty>
            </air:AirPricingInfo>
          </air:AirPricingSolution>


          <air:AirPricingSolution>
            <fruit>cherry</fruit>
          </air:AirPricingSolution>

          <air:AirPricingSolution>
            <fruit>banana</fruit>
          </air:AirPricingSolution>

          <air:AirPricingSolution>
            <fruit>apple</fruit>
          </air:AirPricingSolution>
    </air:LowFareSearchRsp>';



/* keep errors from interfering with operatons */
libxml_use_internal_errors( true );

/* create a basic temporary DOMDocument to copy nodes into */
$tmp=new DOMDocument;
$tmp->formatOutput=true;
$root=$tmp->createElement('root');
$tmp->appendChild( $root );
$tmp->saveXML();

/* Create the main DOMDocument to process the source XML */
$dom=new DOMDocument;
$dom->validateOnParse=false;
$dom->recover=true;
$dom->strictErrorChecking=false;
$dom->loadXML( $xml );
$errors = libxml_get_errors();
libxml_clear_errors();

/* were there errors with the XML? */
if( !empty( $errors ) ){
    /* do stuff */
}

/* 
    create the XPath object and register the namespace so 
    we can query for nodes that use that namespace prefix 
*/
$xp=new DOMXPath( $dom );
$xp->registerNamespace( 'air','http://www.travelport.com/schema/air_v48_0');


/* run the query to find nodes of interest */
$colaps=$xp->query('//air:AirPricingSolution');
if( $colaps->length > 0 ){
    /*
        For each node found create a 
        clone and add to the temp document
    */
    foreach( $colaps as $aps ){
        $clone=$tmp->importNode( $aps->cloneNode( true ), true );
        $tmp->documentElement->appendChild( $clone );
    }
}

/* 
    there is now a dcument with all cloned nodes which
    can be saved or displayed or further manipulated 
*/
printf( '<textarea cols=100 rows=20>%s</textarea>',$tmp->saveXML() );

update

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

libxml_use_internal_errors( true );
$dom=new DOMDocument;
$dom->validateOnParse=false;
$dom->recover=true;
$dom->strictErrorChecking=false;
$dom->loadXML( $xml );
$errors = libxml_get_errors();
libxml_clear_errors();


$tmp=$dom->createDocumentFragment();

$xp=new DOMXPath( $dom );
$xp->registerNamespace( 'air','http://www.travelport.com/schema/air_v48_0');

$colaps=$xp->query('//air:AirPricingSolution');
if( $colaps->length > 0 ){
    foreach( $colaps as $aps ){
        $clone=$aps->cloneNode( true );
        $tmp->appendChild( $clone );
    }
}
$var = $dom->saveXML( $tmp ); # play with $var

Чтобы выбрать конкретный узел на основе определенного атрибута, в данном случае Key, вам нужно немного изменить базовое выражение XPath.

Рассмотреть эти узлы в XML

cherry

банан

яблоко

XPath для их поиска может выглядеть следующим образом:

$col=$xp->query( '//air:AirPricingSolution[ @Key="CherryRed" ]' );

Взгляните на этот превосходный XPath-лист

1 голос
/ 10 ноября 2019

Если вы просто хотите, чтобы каждый из элементов по одному, вы можете выводить данные на верхнем уровне, а не на дочернем уровне ...

if( $hsr->getName() == 'AirPricingSolution' ){
    echo $hsr->asXML();
}

Вы можете просто использовать XPath, чтобы найтиразличные <air:AirPricingSolution> элементы, а затем используйте asXML() на них. Следует помнить одну вещь: поскольку вы используете пространство имен (эфир), вам может потребоваться зарегистрировать его, чтобы запрос XPath работал, так что просто для безопасности - я все равно его регистрирую ...

$Results = simplexml_load_file("data.xml");

$Results->registerXPathNamespace("air", "http://www.travelport.com/schema/air_v48_0");

$airPricings = $Results->xpath("//air:AirPricingSolution");
foreach ( $airPricings as $airPricing ) {
    echo $airPricing->asXML().PHP_EOL;
}

С вашими тестовыми данными (с поправкой на вложенность XML) выдает ...

<air:AirPricingSolution Key="lR26Z14R2BKAVzCGAAAAAA==" TotalPrice="BDT53498" BasePrice="USD444.00" ApproximateTotalPrice="BDT53498" ApproximateBasePrice="BDT37186" EquivalentBasePrice="BDT37186" Taxes="BDT16312" ApproximateTaxes="BDT16312">
        <air:Journey TravelTime="P0DT4H10M0S">
            <air:AirSegmentRef Key="lR26Z14R2BKAWzCGAAAAAA=="/>
        </air:Journey>
        <air:Journey TravelTime="P0DT4H0M0S">
            <air:AirSegmentRef Key="lR26Z14R2BKAYzCGAAAAAA=="/>
        </air:Journey>
        <air:LegRef Key="lR26Z14R2BKAazCGAAAAAA=="/>
        <air:LegRef Key="lR26Z14R2BKAbzCGAAAAAA=="/>
        <air:AirPricingInfo Key="lR26Z14R2BKAczCGAAAAAA==" TotalPrice="BDT26749" BasePrice="USD222.00" ApproximateTotalPrice="BDT26749" ApproximateBasePrice="BDT18593" EquivalentBasePrice="BDT18593" Taxes="BDT8156" ApproximateTaxes="BDT8156" LatestTicketingTime="2020-01-06" PricingMethod="Guaranteed" ETicketability="Yes" PlatingCarrier="MH" ProviderCode="1G" Cat35Indicator="false">
            <air:FareInfoRef Key="lR26Z14R2BKAlzCGAAAAAA=="/>
            <air:FareInfoRef Key="lR26Z14R2BKA0zCGAAAAAA=="/>
            <air:BookingInfo BookingCode="N" BookingCount="9" CabinClass="Economy" FareInfoRef="lR26Z14R2BKAlzCGAAAAAA==" SegmentRef="lR26Z14R2BKAWzCGAAAAAA=="/>
            <air:BookingInfo BookingCode="N" BookingCount="9" CabinClass="Economy" FareInfoRef="lR26Z14R2BKA0zCGAAAAAA==" SegmentRef="lR26Z14R2BKAYzCGAAAAAA=="/>
            <air:TaxInfo Category="BD" Amount="BDT500" Key="lR26Z14R2BKAdzCGAAAAAAAA"/>
            <air:TaxInfo Category="E5" Amount="BDT75" Key="lR26Z14R2BKAezCGAAAAAAAA"/>
            <air:TaxInfo Category="OW" Amount="BDT2000" Key="lR26Z14R2BKAfzCGAAAAAAAA"/>
            <air:TaxInfo Category="UT" Amount="BDT3000" Key="lR26Z14R2BKAgzCGAAAAAAAA"/>
            <air:TaxInfo Category="G1" Amount="BDT407" Key="lR26Z14R2BKAhzCGAAAAAAAA"/>
            <air:TaxInfo Category="H8" Amount="BDT21" Key="lR26Z14R2BKAizCGAAAAAAAA"/>
            <air:TaxInfo Category="MY" Amount="BDT1483" Key="lR26Z14R2BKAjzCGAAAAAAAA"/>
            <air:TaxInfo Category="YQ" Amount="BDT670" Key="lR26Z14R2BKAkzCGAAAAAAAA"/>
            <air:FareCalc>DAC MH KUL 111.00NBC6MSBD MH DAC 111.00NBC6MSBD
                NUC222.00END ROE1.0</air:FareCalc>
            <air:PassengerType Code="ADT"/>
            <air:PassengerType Code="ADT"/>
            <air:ChangePenalty PenaltyApplies="Anytime">
                <air:Amount>BDT3350.0</air:Amount>
            </air:ChangePenalty>
            <air:CancelPenalty NoShow="true" PenaltyApplies="Anytime">
                <air:Percentage>100.00</air:Percentage>
            </air:CancelPenalty>
        </air:AirPricingInfo>
    </air:AirPricingSolution>
<air:AirPricingSolution>
    </air:AirPricingSolution>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...