簡體   English   中英

用php遍歷XML文件

[英]Iterating through XML file with php

我有一個包含以下內容的XML文件:

<property>
  <id>1</id>
  <type>type</type>
  <town>town</town>
  <province>province</province>
  <images>
    <image id="1">
    <url>
      http://www.test.com
    </url>
    <image id="2">
    <url>
      http://www.test.com
    </url>
    <image id="3">
    <url>
      http://www.test.com
    </url>
  </image>

我可以遍歷文件並獲取除圖像URL之外的值。 我正在為具有屬性的元素在元素之后苦苦掙扎。

$count=0;
$id=0;
foreach($xml->children() as $properties) {
    echo "<h1>" . $xml->property[$count]->type . " for sale in " .$xml->property[$count]->town . ", " . $xml->property[$count]->province . "</h1>" . "<br>";
    echo $xml->property[$count]->id . "<br>";
    echo $xml->property[$count]->desc->en . "<br>";

    foreach($xml->property[$count]->children() as $images) {
        echo $xml->property[$count]->images -> image[$id++] -> url;
        $id++;
}
    $count++;
}

但是第二個循環並不太正確。 我將不勝感激一些幫助。

大概是這樣的:

foreach($xml->property[$count]->images as $image) {
    echo $image->url;
}

您尚未共享完整的XML結構,因此尚不清楚文檔根目錄(文檔元素)在哪里。

假設根元素不是<property>但所有<property>元素都是root元素的子元素,則可以通過僅對它們進行迭代來遍歷所有這些<property>元素:

$xml = simplexml_load_file('example.xml');

foreach ($xml->property as $property) {
    printf(
        "<h1>%s for sale in %s, %s</h1>\n", htmlspecialchars($property->id), 
        htmlspecialchars($property->town), htmlspecialchars($property->province)
    );

如您所見,您不需要顯式使用$count變量。 可以,但是不需要。 只是說。

現在,您正在尋找圖像URL。 每個<property>元素都有一個名為<images>子元素,而這些子元素又具有您感興趣的多個<url>元素。

這可以通過xpath查詢來完成(當您深入到多個層次時):

$urls = $property->xpath('images/image/url');
foreach ($urls as $url) {
    printf(" - %s\n", htmlspecialchars(trim($url)));
}

如果您在此處不使用xpath,則需要為每個包含多個子代的單個級別創建一個foreach。 只是一個反例:

foreach ($property->images->image as $image) {
    foreach ($image->url as $url) {
        printf(" - %s\n", htmlspecialchars(trim($url)));
    }
}

我希望這能更好地向您展示遍歷如何在simplexml中工作。 PHP手冊中有一些更棒的材料,名為“ 基本SimpleXML用法” ,它顯示了基本遍歷並還鏈接到更高級的xpath主題。

而且,不要忘記將動態數據輸出到HTML中以正確地對其進行HTML編碼的時間。 我為此使用了htmlspecialchars函數,您需要提供正確的編碼參數,為了簡潔起見,我省略了這些參數。

完整示例:

<?php
/**
 * @link https://stackoverflow.com/questions/28929239/iterating-through-xml-file-with-php
 */

$buffer = <<<XML
<root>
    <property>
        <id>1</id>
        <type>type</type>
        <town>town</town>
        <province>province</province>
        <images>
            <image id="1">
                <url>
                    http://www.test.com
                </url>
            </image>
            <image id="2">
                <url>
                    http://www.test.com
                </url>
            </image>
            <image id="3">
                <url>
                    http://www.test.com
                </url>
            </image>
        </images>
    </property>
    <property>
        <id>1</id>
        <images>
            <image id="1">
                <url>
                    http://www.test.com
                </url>
            </image>
         </images>
    </property>
</root>
XML;


$xml = simplexml_load_string($buffer);

foreach ($xml->property as $property) {
    printf(
        "<h1>%s for sale in %s, %s</h1>\n",
        htmlspecialchars($property->id), htmlspecialchars($property->town), htmlspecialchars($property->province)
    );

    $urls = $property->xpath('images/image/url');
    foreach ($urls as $url) {
        printf(" - %s\n", htmlspecialchars(trim($url)));
    }
}

示例輸出(純文本):

<h1>1 for sale in town, province</h1>
 - http://www.test.com
 - http://www.test.com
 - http://www.test.com
<h1>1 for sale in , </h1>
 - http://www.test.com

使用SimpleXML進行音譯和輸出編碼

通過擴展SimpleXMLElement的每個字符串值,可以采用一種全局應用音譯(去除重音)和HTML編碼( htmlspecialchars )的方法。 有一個缺點: SimpleXMLElement不能具有私有屬性(因為這些屬性都是魔術),但是您可以創建靜態全局變量。 為了保留音譯器的實例,這就足夠了。 為了處理字符串值, __toString()魔術方法SimpleXMLElement一起使用效果很好:

/**
 * Transliterate and HTML encode
 *
 * Class XMLTransliterated
 */
class XMLTransliterated extends SimpleXMLElement
{
    public static $transliterator;

    public function __toString()
    {
        $transliterator = &self::$transliterator;
        $transliterator || $transliterator = Transliterator::create("Latin-ASCII");

        $transliterated = $transliterator->transliterate($this);

        return htmlspecialchars(trim($transliterated), ENT_QUOTES | ENT_HTML5, 'UTF-8');
    }
}

要從字符串操作中受益,您需要做的就是在創建SimpleXMLElement時使用此類名XMLTransliterated (或使用任何您要命名的類):

$xml = simplexml_load_string($buffer, 'XMLTransliterated');

-或-這對於simplexml非常特殊,您可以稍后使用一些轉換技巧來更改類:

$xml = simplexml_import_dom(dom_import_simplexml($xml), 'XMLTransliterated');

這將使以下代碼使用XMLTransliterated而不是先前的不太具體的SimpleXMLElement,因此該代碼在很大程度上保持不變(請注意,可以安全地刪除htmlspecialcharstrim調用,因為現在訪問它們的字符串值時會自動調用它們。 SimpleXMLElement ):

$xml = simplexml_load_string($buffer, 'XMLTransliterated');

foreach ($xml->property as $property) {
    printf(
        "<h1>%s (%s) for sale in %s, %s</h1>\n",
        $property->id, $property->type, $property->town, $property->province
    );

    $urls = $property->xpath('images/image/url');
    foreach ($urls as $url) {
        printf(" - %s\n", $url);
    }
}

但是輸出將把“ Schloß ”變成“ schloss ”,“ tôwn ”變成“ town ”,“ provincé ”變成“ province ”。

Transliterator需要PHP 5.4,並且您已啟用了Intl擴展 (如果未啟用,則應具有)。

或者,您也可以使用iconv庫中音譯 但是請注意,這會產生稍微不同的輸出:

$transliterated = iconv('UTF-8', 'ASCII//IGNORE//TRANSLIT', $this);

更多相關的音譯問題:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM