在PHP中复制xml的一部分

63lcw9qa  于 2022-12-17  发布在  PHP
关注(0)|答案(2)|浏览(123)

我正在尝试从现有XML内容中提取一部分。例如:我想从给定的xml中提取整个<air:AirPricingSolution> ..... </air:AirPricingSolution>块。我的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的整个块,因为它是。

x9ybnkn6

x9ybnkn61#

使用标准的DOMDocumentDOMXpath,可以非常直接地提取(克隆)文档的某些部分,以后可以根据需要使用这些部分。

$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() );

更新

与关于使用文档片段而不是整个文档(这是一个更干净的解决方案)的绝对正确的评论一致,这就是可能的做法。

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中的这些节点

<air:AirPricingSolution Key="CherryRed">
    <fruit>cherry</fruit>
</air:AirPricingSolution>
<air:AirPricingSolution Key="Bananarama">
    <fruit>banana</fruit>
</air:AirPricingSolution>
<air:AirPricingSolution Key="GoldenDelicious">
    <fruit>apple</fruit>
</air:AirPricingSolution>

查找它们的XPath可能如下所示:

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

看一下这个excellent XPath cheatsheet

h7appiyu

h7appiyu2#

如果您只想一次输出一个元素,则可以在顶层而不是子层输出数据...

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

您可以简单地使用XPath来查找各种<air:AirPricingSolution>元素,然后对它们使用asXML(),需要注意的一点是,由于您使用的是名称空间(air),因此可能需要注册它以使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>

相关问题