2017-01-29 3 views
1

YouTube의 상위 15 개 동영상 피드를 구문 분석하려고합니다. 내가 구문 분석하려고 공급의 발췌는 다음과 같습니다 :SimpleXML을 사용하여 PHP에서 네임 스페이스로 XML 문서를 쉽게 파싱하는 방법은 무엇입니까?

<entry> 
    <title>The Title</title> 
    <link href="http://example.com" /> 
    <media:thumbnail url="http://example.com/image.png" /> 
    <media:description>The Description</media:description> 
    <media:statistics views="123456" /> 
    <pubDate>29/01/2017</pubDate> 
</entry> 

나는 <media:로 시작하는 태그를 사용하는 값 ​​중 하나를 캡처 할 수 없습니다입니다. 다음 코드를 사용하여 데이터를 구문 분석합니다. 주석 처리 된 행은 작동하지 않는 행입니다.

foreach ($xml->entry as $val) { 
    echo "<item>".PHP_EOL; 
    echo "<title>".$val->title."</title>".PHP_EOL; 
    echo "<link>".$val->link["href"]."</link>".PHP_EOL; 
    //echo "<image>".$val->media:thumbnail["url"]."</image>".PHP_EOL; 
    //echo "<description>".$val->media:description."</description>".PHP_EOL; 
    //echo "<views>".$val->media:statistics["views"]."</views>".PHP_EOL; 
    echo "<pubDate>".$val->published."</pubDate>".PHP_EOL; 
    echo "</item>".PHP_EOL; 
} 

네임 스페이스를 설정하지 않고이 태그의 값을 어떻게 얻을 수 있습니까? 을 $xml->entry에서 실행해도 네임 스페이스 요소가 표시되지 않습니다. XML을 배열로 변환하는 기능이 내장되어 있습니까?

+0

귀하의 XML 형식이 올바르지 않습니다 (즉, 유효하지 않습니다). [XML 1.0의 W3C 네임 스페이스] (https://www.w3.org/TR/REC-xml-names/#ns-using)에 따르면 : xml이나 xmlns가 아닌 네임 스페이스 접두어는 반드시 네임 스페이스 선언 특성 *에서 선언되었습니다. 그러므로'media' 접두사를 선언해야합니다. – Parfait

+0

DOM + Xpath를 사용하면 훨씬 어려워집니다. DOMXpath 인스턴스에 자신의 접두사를 등록하고 DOMXpath :: evaluate()을 사용하여 노드 목록과 값을 가져옵니다. – ThW

+0

지금 당장 풀 답변을 쓸 시간이 없지만 찾고있는 방법은 ['-> children()'] (http://php.net/manual/en/simplexmlelement.children. PHP). 접두사가 아닌 실제 네임 스페이스 URI ('xmlns : media' 속성에서)를 하드 코딩하는 것이 좋겠지 만'$ val-> children ('media', true) -> description ' 소스 문서가 다른 접두사로 다시 생성되는 경우 – IMSoP

답변

0

내 대답은 code provided by IMSoP입니다. 이 미래에 누군가를 도울 수

foreach ($xml->children(NS_ATOM)->entry as $entry) { 
    echo "<item>".PHP_EOL; 
    echo "<title>".$entry->title."</title>".PHP_EOL; 
    echo "<link>".$entry->link->attributes(null)->href."</link>".PHP_EOL; 
    echo "<image>".$entry->children(NS_MEDIA)->group->children(NS_MEDIA)->thumbnail->attributes(null)->url."</image>".PHP_EOL; 
    echo "<description>".$entry->children(NS_MEDIA)->group->children(NS_MEDIA)->description."</description>".PHP_EOL; 
    echo "<guid>".$entry->children(NS_YT)->videoId."</guid>".PHP_EOL; 
    echo "<views>".$entry->children(NS_MEDIA)->group->children(NS_MEDIA)->community->children(NS_MEDIA)->statistics->attributes(null)->views."</views>".PHP_EOL; 
    echo "<pubDate>".$entry->published."</pubDate>".PHP_EOL; 
    echo "</item>".PHP_EOL; 
} 

희망 : PHP의 내가 OP 유사한 XML을 사용하여, 상기 링크에서 적응했다하여 결국 니펫을. 지금까지 XML 이름 공간 파싱의 가장 쉬운 예가있었습니다.

0

XPath에 대한 형제 인 XSLT을 고려해보십시오. 본질적으로 XML을 변형하고 있으므로 실제로는 선택 값을 파싱하지 않습니다. XSLT를 사용하면 foreach 루프가 필요하지 않으며 네임 스페이스를 적절히 처리 할 수 ​​있습니다.

간단한 XML(@IMSoP에서)

: XSLT 아래와 같이 사실

은 (SimpleXML 쿼리 및 평가 XPath)를 <feed ...> 루트에 싸여 게시 된 XML을 사용하여 상기 방법 중 가장 빠른

$time_start = microtime(true); 

$xml = file_get_contents('YoutubeFeed.xml'); 
$document = new SimpleXMLElement($xml); 
define('NS_ATOM', 'http://www.w3.org/2005/Atom'); 
define('NS_MEDIA', 'http://search.yahoo.com/mrss/'); 

foreach ($document->children(NS_ATOM)->entry as $entry) { 
    echo "<item>".PHP_EOL; 
    echo "<title>".$entry->title."</title>".PHP_EOL; 
    echo "<link>".$entry->link->attributes(null)->href."</link>".PHP_EOL; 
    echo "<image>".$entry->children(NS_MEDIA)->thumbnail->attributes()->url."</image>".PHP_EOL; 
    echo "<description>".$entry->children(NS_MEDIA)->description."</description>".PHP_EOL; 
    echo "<guid>".$entry->children(NS_MEDIA)->guid."</guid>".PHP_EOL; 
    echo "<views>".$entry->children(NS_MEDIA)->statistics->attributes()->views."</views>".PHP_EOL; 
    echo "<pubDate>".$entry->published."</pubDate>".PHP_EOL; 
    echo "</item>".PHP_EOL; 
} 

타이밍

echo "SimpleXML: " . (microtime(true) - $time_start) ."\n"; 
# SimpleXML: 0.0014688968658447 
,

XPATH(@ThW부터)

$time_start = microtime(true); 

$xml = file_get_contents('YoutubeFeed.xml'); 
$document = new DOMDocument(); 
$document->loadXml($xml); 

$xpath = new DOMXpath($document); 
$xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom'); 
$xpath->registerNamespace('media', 'http://search.yahoo.com/mrss/'); 

foreach ($xpath->evaluate('//atom:entry') as $entry) { 
    echo "<item>".PHP_EOL; 
    echo "<title>". $xpath->evaluate('string(atom:title)', $entry)."</title>".PHP_EOL; 
    echo "<link>". $xpath->evaluate('string(atom:link/@href)', $entry)."</link>".PHP_EOL; 
    echo "<image>". $xpath->evaluate('string(media:thumbnail/@url)', $entry)."</image>".PHP_EOL; 
    echo "<description>". $xpath->evaluate('string(media:description)', $entry)."</description>".PHP_EOL; 
    echo "<guid>". $xpath->evaluate('string(media:guid)', $entry)."</description>".PHP_EOL; 
    echo "<views>".$xpath->evaluate('string(media:statistics/@views)', $entry)."</guid>".PHP_EOL; 
    echo "<pubDate>". $xpath->evaluate('string(atom:pubdate)', $entry)."</views>".PHP_EOL; 
    echo "</item>".PHP_EOL; 
} 

타이밍

echo "XPATH: " . (microtime(true) - $time_start) ."\n"; 
# XPATH: 0.0012829303741455 

XSLT

$time_start = microtime(true); 

$xml = file_get_contents('YoutubeFeed.xml'); 
$document = new DOMDocument(); 
$document->loadXml($xml); 

$xslstr = '<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
       xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" 
       exclude-result-prefixes="atom media"> 
<xsl:output version="1.0" encoding="UTF-8" indent="yes" /> 
<xsl:strip-space elements="*"/> 

    <xsl:template match="feed"> 
    <xsl:apply-templates select="atom:entry"/> 
    </xsl:template> 

    <xsl:template match="atom:entry"> 
     <item> 
     <title><xsl:value-of select="atom:title"/></title> 
     <link><xsl:value-of select="atom:link/@href"/></link> 
     <image><xsl:value-of select="atom:thumbnail/@url"/></image> 
     <description><xsl:value-of select="media:description"/></description> 
     <guid><xsl:value-of select="media:guid"/></guid> 
     <views><xsl:value-of select="media:statistics/@views"/></views> 
     <pubDate><xsl:value-of select="atom:pubdate"/></pubDate> 
     </item> 
    </xsl:template> 
</xsl:stylesheet>'; 

$xsl = new DOMDocument; 
$xsl->loadXML($xslstr); 

// Configure the transformer 
$proc = new XSLTProcessor; 
$proc->importStyleSheet($xsl); 

// Transform XML source 
$newXML = $proc->transformToXML($document); 

// Echo string output 
echo $newXML; 

타이밍

더욱 <entry> 노드, 복사 태그 500 선에 아이들과 함께 3,691,363,210
echo "XSLT: " . (microtime(true) - $time_start) ."\n"; 
# XSLT: 0.00098896026611328 

는, XSLT는 훨씬 더 확장 할 수 있습니다. 아래의 단위는 초입니다.

# SimpleXML: 0.62154388427734 

# XPATH: 0.68382000923157 

# XSLT: 0.011976957321167