douqudi5282 2013-12-01 22:57
浏览 80
已采纳

PHP / SimpleXML / XPath通过同一元素中的另一个属性获取属性值

I have this XML (from a pptx file):

<Relationships>
    <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image2.png"/>
    <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image1.wmf"/>
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout1.xml"/>
</Relationships>

I want to pull the Target attribute from a Relationship element, and I know the Id value.

I could do it with SimpleXML if I iterate through the nodes (like this question)

$resxml = simplexml_load_file('zip://my.pptx#ppt/slides/_rels/slide1.xml.rels');
echo $resxml->Relationship[0]->attributes()->Target;

But I would like to get it using xpath using this sort of idea. Whatever I do in xpath returns an empty object when I search for something like 'rId3'. I thought it would be the below xpath statement, but it returns an empty object. I have tried about 50 combimations and found a lot of similar but not identical issues when searching:

$image = $resxml->xpath("/Relationships/Relationship[@Id='rId3']/@Target"); 
print_r($image);

I guess I will just end up iterating through all the nodes but it seems inefficient. My server appears to have XPath in the Dom available and SimpleXML enabled.

  • 写回答

2条回答 默认 最新

  • doutu9810 2013-12-01 23:58
    关注

    I think you problem might be the namespace. PPTX Relationship files use the namespace "http://schemas.microsoft.com/package/2005/06/relationships". But SimpleXmls xpath does it's own magic, too. If the file contains the namespace (check the source) you have to register an own prefix for it.

    $xml = <<<'XML'
    <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
    <Relationships
     xmlns="http://schemas.microsoft.com/package/2005/06/relationships">
     <Relationship Id="rId1"
     Type="http://schemas.microsoft.com/office/2006/relationships/image"
     Target="http://en.wikipedia.org/images/wiki-en.png"
     TargetMode="External" />
     <Relationship Id="rId2"
     Type="http://schemas.microsoft.com/office/2006/relationships/hyperlink"
     Target="http://www.wikipedia.org"
     TargetMode="External" />
    </Relationships> 
    XML;
    
    $dom = new DOMDocument();
    $dom->loadXml($xml);
    $xpath = new DOMXpath($dom);
    $xpath->registerNamespace('r', 'http://schemas.microsoft.com/package/2005/06/relationships');
    
    var_dump(
      $xpath->evaluate("string(/r:Relationships/r:Relationship[@Id='rId2']/@Target)", NULL, FALSE)
    );
    

    Output:

    string(24) "http://www.wikipedia.org"
    

    Xpath does not know something like a default namespace. Without a prefix you look for elements without any namespace. Attributes don't have a namespace if not explicitly prefixed.

    To make the confusion complete, do the PHP functions (SimpleXMLElement::xpath(), DOMXpath::query() and DOMXpath::evaluate()) automatically register the namespace definitions of the used context. The third argument allows to disable that behaviour.

    Unlike the other two functions, DOMXpath::evaluate() can return scalars directly.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 求学软件的前人们指明方向🥺
  • ¥50 如何增强飞上天的树莓派的热点信号强度,以使得笔记本可以在地面实现远程桌面连接
  • ¥15 MCNP里如何定义多个源?
  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn
  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services