【问题标题】:Looping XML containing a few child and children to output as a table in PHP循环包含一些子项和子项的 XML 以在 PHP 中以表格形式输出
【发布时间】:2021-04-04 05:31:24
【问题描述】:
<?xml version="1.0" encoding="utf-8"?>
    <Agenda>
        <responseMessage>Success.</responseMessage>
        <jobs>
            <trip>
                <header>
                    <reservation_number>10562</reservation_number>
                    <recipient_first>John</recipient_first>
                    <recipient_middle>H</recipient_middle>
                    <recipient_last>Doe</recipient_last>
                </header>
                <legs>
                    <leg>
                        <trip_id>42390</trip_id>
                        <leg_status>Active</leg_status>
                        <pickup_date>12/24/2020</pickup_date>
                        <pickup_time>0600</pickup_time>
                        <pickup_state>New York</pickup_state>
                        <pickup_country>USA</pickup_country>
                        <dropoff_state>Pennsylvania</dropoff_state>
                        <dropoff_country>USA</dropoff_country>
                    </leg>
                    <leg>
                        <trip_id>42391</trip_id>
                        <leg_status>Canceled</leg_status>
                        <pickup_date>01/02/2021</pickup_date>
                        <pickup_time>1800</pickup_time>
                        <pickup_state>Pennsylvania</pickup_state>
                        <pickup_country>USA</pickup_country>
                        <dropoff_state>New York</dropoff_state>
                        <dropoff_country>USA</dropoff_country>
                    </leg>
                </legs>
                <secondary_services>
                    <service>
                        <service_leg_id>42390</service_leg_id>
                        <service_name>Tolls</service_name>
                        <service_rate>3.00</service_rate>
                        <service_quantity>1</service_quantity>
                    </service>
                    <service>
                        <service_leg_id>42390</service_leg_id>
                        <service_name>addtl.miles</service_name>
                        <service_rate>3.40</service_rate>
                        <service_quantity>25</service_quantity>
                    </service>
                    <service>
                        <service_leg_id>42391</service_leg_id>
                        <service_name>Tolls</service_name>
                        <service_rate>18.00</service_rate>
                        <service_quantity>1</service_quantity>
                    </service>
                    <service>
                        <service_leg_id>42391</service_leg_id>
                        <service_name>addtl.miles</service_name>
                        <service_rate>3.40</service_rate>
                        <service_quantity>29</service_quantity>
                    </service>
                </secondary_services>
            </trip>
            <trip>
                <header>
                    <reservation_number>10575</reservation_number>
                    <recipient_first>Emily</recipient_first>
                    <recipient_middle></recipient_middle>
                    <recipient_last>Santana</recipient_last>
                </header>
                <legs>
                    <leg>
                        <trip_id>64593</trip_id>
                        <leg_status>Active</leg_status>
                        <pickup_date>12/27/2020</pickup_date>
                        <pickup_time>1700</pickup_time>
                        <pickup_state>New York</pickup_state>
                        <pickup_country>USA</pickup_country>
                        <dropoff_state>Connecticut</dropoff_state>
                        <dropoff_country>USA</dropoff_country>
                    </leg>
                    <leg>
                        <trip_id>64594</trip_id>
                        <leg_status>Active</leg_status>
                        <pickup_date>01/04/2021</pickup_date>
                        <pickup_time>1200</pickup_time>
                        <pickup_state>Connecticut</pickup_state>
                        <pickup_country>USA</pickup_country>
                        <dropoff_state>New York</dropoff_state>
                        <dropoff_country>USA</dropoff_country>
                    </leg>
                </legs>
                <secondary_services>
                    <service>
                        <service_leg_id>64593</service_leg_id>
                        <service_name>Tolls</service_name>
                        <service_rate>0.00</service_rate>
                        <service_quantity>0</service_quantity>
                    </service>
                    <service>
                        <service_leg_id>64593</service_leg_id>
                        <service_name>addtl.miles</service_name>
                        <service_rate>3.40</service_rate>
                        <service_quantity>10</service_quantity>
                    </service>
                    <service>
                        <service_leg_id>64594</service_leg_id>
                        <service_name>Tolls</service_name>
                        <service_rate>04.00</service_rate>
                        <service_quantity>1</service_quantity>
                    </service>
                    <service>
                        <service_leg_id>64594</service_leg_id>
                        <service_name>addtl.miles</service_name>
                        <service_rate>3.40</service_rate>
                        <service_quantity>11</service_quantity>
                    </service>
                </secondary_services>
            </trip>
        </jobs>
    </Agenda>

我无法通过 foreach 循环循环输出这样的表。

Reservation ID Status Name Date Time PU Location DO Location Tolls Addlt. Miles
10562-42390 Active John H Doe 12/24/2020 0600 New York, USA Pennsylvania, USA 3.00 25
10562-42391 Canceled John H Doe 01/02/2021 1800 Pennsylvania, USA New York, USA 18.00 29
10575-64593 Active Emily Santana 12/27/2020 1700 New York, USA Connecticut, USA 0.00 10
10575-64594 Active Emily Santana 01/04/2021 1200 Connecticut, USA New York, USA 4.00 11

我在另一个 foreach 循环中尝试了一个带有键和值的 foreach 循环,但我无法将 service 元素与 leg 元素匹配,因为它们具有独立的循环。

【问题讨论】:

  • 您能否展示进行匹配的代码,因为它可能比提出全新的解决方案更容易修复。

标签: php xml xpath foreach xmldom


【解决方案1】:

考虑XSLT,这是一种专用语言,旨在转换 XML 文件,例如处理所有值的连接和腿 ID 的匹配。如果需要,XSLT 甚至可以转换为 HTML。 PHP 可以使用 DOMDocument 库运行带有 xsl 类的 XSLT 1.0 脚本。

XSLT (另存为.xsl文件,特殊的.xml文件)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:key name="leg_key" match="leg" use="trip_id" />
    
    <xsl:template match="/Agenda">
        <xsl:copy>
            <xsl:apply-templates select="descendant::leg[generate-id() =
                                                         generate-id(key('leg_key', trip_id)[1])]"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="leg">
        <xsl:copy>
            <xsl:variable name="curr_leg_id" select="trip_id"/>
            <Reservation_id>
                <xsl:value-of select="concat(ancestor::trip/header/reservation_number, '-', trip_id)"/>
            </Reservation_id>
            <Status><xsl:value-of select="leg_status"/></Status>
            <Name><xsl:value-of select="concat(ancestor::trip/header/recipient_first, ' ', 
                                               ancestor::trip/header/recipient_middle, ' ', 
                                               ancestor::trip/header/recipient_last)"/></Name>
            <Date><xsl:value-of select="pickup_date"/></Date>
            <Time><xsl:value-of select="pickup_time"/></Time>
            <PU_location><xsl:value-of select="concat(pickup_state, ' ', pickup_country)"/></PU_location>
            <DO_location><xsl:value-of select="concat(dropoff_state, ' ', dropoff_country)"/></DO_location>
            <Tolls>
                <xsl:value-of select="ancestor::trip/secondary_services/service[service_leg_id = $curr_leg_id and
                                                                                service_name='Tolls']/service_rate"/>
            </Tolls>
            <Addl>
                <xsl:value-of select="ancestor::trip/secondary_services/service[service_leg_id = $curr_leg_id and
                                                                                service_name='addtl.miles']/service_quantity"/>
            </Addl>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Online Demo

PHP (使用$new_xml 满足最终最终使用需求)

// LOAD XML
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->load('/path/to/Input.xml');

// LOAD XSLT 
$xsl = new DOMDocument('1.0', 'UTF-8');   
$xsl->load('/path/to/XSLT_Script.xsl');

// INITIALIZE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// TRANSFORM ORIGINAL DOCUMENT
$new_xml = $proc->transformToDoc($xml);

// ECHO TO SCREEN 
echo $new_xml->saveXML();

// SAVE TO FILE
file_put_contents('/path/to/Output.xml', $new_xml);

【讨论】:

  • 你绝对是山羊?!应用 XSLT 的强大功能来转换 XML 数据提供了无限量的功能(尤其是匹配)。谢谢!
  • 是的!终于有人看到了 XSLT 的强大功能(xslt 线程之外)!编码愉快!
  • 也许不仅仅是新年决心:认识到 XSLT 的力量 - 因此新年快乐 :+)
  • @Parfait 谢谢!您只需让别人看到 XSLT ?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 2018-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多