如何使用PHP中的xhtml:link解析XML?

时间:2019-02-15 19:58:23

标签: php xml parsing xhtml hreflang

目标:

  • 导入外部XML文件(在本例中为内联)
  • 获取,保存为变量
  • 找到具有href-lang =“ fr-ca”属性的,获取href值,保存到变量中
  • 将两者都插入数据库

我遇到的问题:我什至无法使PHP意识到xhtml:link是项的childNode;即使我只是为吐出nodeValue,它也会忽略所有子节点。

我正在使用/尝试的代码:

<?php
$xml = <<< XML
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <loc>https://www.example.com/ca/en/cat/categories/series/07660/</loc>
  <lastmod>2018-11-07</lastmod>
  <changefreq>daily</changefreq>
  <priority>1.0</priority>
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="en-ae" href="https://www.example.com/ae/en/cat/categories/series/07660/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="de-at" href="https://www.example.com/at/de/cat/07660/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="en-au" href="https://www.example.com/au/en/cat/categories/series/07660/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="en-ca" href="https://www.example.com/ca/en/cat/categories/series/07660/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="fr-ca" href="https://www.example.com/ca/fr/cat/categories/series/07660/" />
</url>
<url xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <loc>https://www.example.com/ca/en/cat/categories/series/07683/</loc>
  <lastmod>2018-11-07</lastmod>
  <changefreq>daily</changefreq>
  <priority>1.0</priority>
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="en-ae" href="https://www.example.com/ae/en/cat/categories/series/07683/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="de-at" href="https://www.example.com/at/de/cat/07683/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="en-au" href="https://www.example.com/au/en/cat/categories/series/07683/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="fr-be" href="https://www.example.com/be/fr/collections/07683/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="nl-be" href="https://www.example.com/be/nl/collecties/07683/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="en-bh" href="https://www.example.com/bh/en/cat/07683/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="en-ca" href="https://www.example.com/ca/en/cat/categories/series/07683/" />
  <xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="alternate" hreflang="fr-ca" href="https://www.example.com/ca/fr/cat/categories/series/07683/" />
</url>
</urlset>
XML;

$urlsxml = new DOMDocument;
$urlsxml->loadXML($xml);
$urls = $urlsxml->getElementsByTagName('url');

for ($i = 0; $i < $urls->length; $i++) {

      echo $urls->item($i)->nodeValue;
      echo $urls->getElementsByTagName("xhtml:link")->attributes->getNamedItem("hreflang")->nodeValue;

      // INSERT INTO DB

}

?>

没有主意;任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

XML使用两个没有别名的名称空间http://www.sitemaps.org/schemas/sitemap/0.9和带有别名http://www.w3.org/1999/xhtml的{​​{1}}。要读取带有名称空间的XML,您应该使用DOM方法的xhtml变体。

*NS

第一个参数是名称空间URI,第二个参数是本地名称(带前缀的节点名称)。在这种情况下,最好对名称空间URI使用常量/变量。

一个更舒适的选择是Xpath。它允许您使用位置路径和条件来获取节点。

$urls = $urlsxml->getElementsByTagNameNS(
  'http://www.sitemaps.org/schemas/sitemap/0.9', 'url'
);

$urls[$i]->getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'link');

输出:

$document = new DOMDocument;
$document->loadXML($xml);
// create an xpath instance for the document
$xpath = new DOMXpath($document);
// register the namespaces for your own prefixes
$xpath->registerNameSpace('s', 'http://www.sitemaps.org/schemas/sitemap/0.9');
$xpath->registerNameSpace('x', 'http://www.w3.org/1999/xhtml');

// iterate all sitemap url elements
foreach ($xpath->evaluate('//s:url') as $url) {
  $data = [
    // get the sitemap loc child element as a string
    'loc' => $xpath->evaluate('string(s:loc)', $url),
    // get the href attribute of the xhtml link element (with language condition)
    'fr-ca' => $xpath->evaluate('string(x:link[@hreflang="fr-ca"]/@href)', $url),
  ];
  var_dump($data);
}

Xpath中的array(2) { ["loc"]=> string(58) "https://www.example.com/ca/en/cat/categories/series/07660/" ["fr-ca"]=> string(58) "https://www.example.com/ca/fr/cat/categories/series/07660/" } array(2) { ["loc"]=> string(58) "https://www.example.com/ca/en/cat/categories/series/07683/" ["fr-ca"]=> string(58) "https://www.example.com/ca/fr/cat/categories/series/07683/" } 将列表中的第一个节点转换为字符串。它使您可以避免显式访问节点对象属性。例如,string()可以写为$xpath->evaluate('s:loc', $url)->item(0)->textContent;。如果不存在匹配的节点,则与属性访问不同,Xpath强制转换不会因错误而失败。它将返回一个空字符串。

答案 1 :(得分:0)

插入数据库的实际行为超出了此处代码的范围,但是要解析XML,您可以执行以下操作(基于XML的本地保存副本,而不是使用{{1} }语法)〜文件名仅用于标识。

最初,我认为这需要在XPath表达式中注册android:background="@android:color/transparent" 并使用它,但事实并非如此-对每个heredoc节点进行简单的XPath查询就足够了〜使用父节点namespace作为查询的参考节点。

url

答案 2 :(得分:-1)

如果将XML文件放入变量中,则可以使用循环提取值:

$xml = file_get_contents("your_xml_file");
$tags = explode("<", $xml);
$loc = "not found";
$frhref = "not found";

foreach ($tags as $tag){
    if(strpos($tag, "loc>") === 0){
        $loc = substr($tag, 4);
    }
    if(strpos($tag, "xhtml:link") === 0){
        $at = strpos($tag, "hreflang") + 9;
        $lang = substr($tag, $at, 7);
        if($lang == '"fr-ca"'){
            $at = strpos($tag, "href=") + 6;
            $_href = substr($tag, $at);
            $until = strpos($_href, '"');
            $frhref = substr($_href, 0, $until);
        }
    }
}
echo $loc, " ", $frhref; //put them in your db

我用您的内容进行了测试:https://3v4l.org/1laON