2016-11-12 1 views
1

PHP 무시 네임 스페이스에 DOMXPath과 XML 속성을 얻기 :내가 XML 파일이

<Receipt Version="2.0" ReceiptDate="2012-08-30T23:10:05Z" CertificateId="A656B9B1B3AA509EEA30222E6D5E7DBDA9822DCD" xmlns="http://schemas.microsoft.com/windows/2012/store/receipt"> 
.... 
</Receipt> 

을 나는 PHP에서 XPath를 함께 CertificateId을 얻으려고 :

$doc = new DOMDocument(); 
$doc->loadXML($v); 
$xpath = new DOMXPath($doc); 
$query = 'string(/Receipt/@CertificateId)'; 
$id = $xpath->evaluate($query); 

$id 무효이며 Msft이 있기 때문에 이 링크를 포기 했으므로 namespace에 액세스 할 수 없습니다. 즉, CertificateId 네임 스페이스를 무시해야합니다. XML에서 네임 스페이스 문자열을 제거하면 코드가 작동하지만 XML을 편집하지 않는 것이 좋습니다. local-name() XPath 함수를 사용하여이 작업을 수행 할 수 있다는 것을 알고 있지만 어떻게 PHP로이 작업을 수행 할 수 있습니까?


는 여기에 내가 DOM에서 읽어 방법은 다음과 같습니다

 $id = null; 
     if ($doc->childNodes->length > 0) 
     { 
      $root = $doc->childNodes->item(0); 
      if ($root->nodeName == 'Receipt') 
       $id = $root->attributes->getNamedItem('CertificateId')->nodeValue; 
     } 

이 코드 네임 스페이스를 무시합니다. 그러나 XPath를 사용하여이를 수행하는 방법은 무엇입니까?

+0

*이 * 왜/당신이 * * 사용할 수없는 방법 '로컬 이름이 "나는 그것이 로컬 이름()'의 XPath의 기능,하지만 난 PHP에서이 작업을 수행 할 수있는 방법?'수행 할 수있어"()'PHP에서? – har07

+0

정보 수정 방법을 찾을 수 없습니다. 까다로운 구문 – Tertium

답변

1

XPath 2.0에서 네임 스페이스 부분에 와일드 카드 (string(//*:Receipt/@CertificateId))를 사용할 수 있습니다. 그러나 PHP는 현재 내가 아는 한 XPath 1.0 만 구현합니다.

당신은 네임 스페이스를 등록 할 수 있습니다 :

$xpath->registerNamespace('x', 'http://schemas.microsoft.com/windows/2012/store/receipt'); 
$query = 'string(//x:Receipt/@CertificateId)'; 

을하거나 심지어 특정 네임 스페이스 언급하지 않으려는 경우에만 속성을 선택합니다 그렇지 않으면

$query = 'string(//*/@CertificateId)'; 

을, 당신은 local-name를 사용하도록 강요 :

$query = "string(//*[local-name(.) = 'Receipt']/@CertificateId)"; 
+0

아니요, 어떤 부분을 확인해야 할지를 알고 싶지 않습니다. 나는 단지 무시하고 싶다. 내 업데이트를 참조하십시오. – Tertium

+0

Receipt 요소 만 확인해야합니다. // */@ CertificateId는 시도한/Receipt/*/@ CertificateId 요소의 attr 값을 표시합니다. 작동하지 않습니다. 그리고 네, PHP는 xpath 2.0을 지원하지 않습니다 – Tertium

+0

고마워, 그 작품! 가장 분명한 구문이 아니라 PHP 매뉴얼에있을 수 있습니다. Btw는 시작 슬래시가 하나라도 작동합니다. – Tertium

0

여기서는 네임 스페이스를 무시할 필요가 없습니다. 네임 스페이스는 기존 URL 일 필요는 없습니다. 전 세계적으로 유일한 URNs이어야합니다. 많은 사람들이 자신이 소유 한 도메인의 URL을 사용합니다. 그런 식으로 갈등의 기회는별로 없습니다. 그리고 거기에 몇 가지 문서를 넣을 수 있습니다.

$xml = <<<'XML' 
<Receipt 
    Version="2.0" 
    ReceiptDate="2012-08-30T23:10:05Z" 
    CertificateId="A656B9B1B3AA509EEA30222E6D5E7DBDA9822DCD" 
    xmlns="http://schemas.microsoft.com/windows/2012/store/receipt"> 
</Receipt> 
XML; 

$document = new DOMDocument(); 
$document->loadXml($xml); 
$xpath = new DOMXpath($document); 
$xpath->registerNamespace(
    'sr', 'http://schemas.microsoft.com/windows/2012/store/receipt' 
); 
var_dump(
    $xpath->evaluate('string(//sr:Receipt/@CertificateId)') 
); 

출력 :

string(40) "A656B9B1B3AA509EEA30222E6D5E7DBDA9822DCD" 

항아리 네임 스페이스에 대한 예는

당신이 돈 경우 rfc6321 '

그냥에 대한 접두사를 등록, XPath는에 네임 스페이스를 사용하려면 Xpath (왜 상상할 수없는)를 사용하고 싶습니다. 네임 스페이스를 인식하는 DOM 메서드 및 속성을 사용할 수 있습니다.

$id = null; 
if ($document->childNodes->length > 0) { 
    $node = $document->childNodes->item(0); 
    if (
    $node->localName == 'Receipt' && 
    $node->namespaceURI == 'http://schemas.microsoft.com/windows/2012/store/receipt' 
) { 
    $id = $node->getAttributeNS(null, 'CertificateId'); 
    } 
} 
var_dump($id); 
+0

다시, 나는이 버그가 많은 오래된 것들에 무엇이 있는지 알고 싶지도 않고, 건너 뛰지 않는다면 몇 가지 속성이 있다고 가정합니다. 그 깨진 네임 스페이스가 거의 정규 표현식을 사용하게 만들었습니다 – Tertium

+0

네임 스페이스가 손상되지 않았지만 기존 URL 일 필요는 없습니다. 그것은 다른 네임 스페이스와 똑같이 작동합니다. 설명을 주신 덕분에 – ThW

+0

주셔서 감사합니다. – Tertium

관련 문제