我有这个XML(来自pptx文件):
<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>
我想从 Relationship 元素中提取 Target 属性,并且我知道 Id 值。
如果我遍历节点(like this question)
,我可以使用SimpleXML$resxml = simplexml_load_file('zip://my.pptx#ppt/slides/_rels/slide1.xml.rels');
echo $resxml->Relationship[0]->attributes()->Target;
但我想使用xpath using this sort of idea来获取它。无论我在xpath中做什么,当我搜索像'rId3'这样的东西时,都会返回一个空对象。我以为它将是下面的xpath语句,但它返回一个空对象。我尝试了大约50个组合,并在搜索时发现了许多相似但不完全相同的问题:
$image = $resxml->xpath("/Relationships/Relationship[@Id='rId3']/@Target");
print_r($image);
我想我最终会迭代遍历所有节点但看起来效率低下。我的服务器似乎在Dom可用和启用SimpleXML中有XPath。
答案 0 :(得分:1)
谢谢。您的出色答案是我找到解决方案的关键。阅读完帖子后,我在Stack交换中的其他地方发现SimpleXML删除了第一个节点上的命名空间属性。我把问题命名空间作为问题,但在查看树时只查看了simpleXML输出。在看真实来源时,你让我正确。
我使用简单XML的解决方案如下所示:
$resxml->registerXPathNamespace('r', 'http://schemas.openxmlformats.org/package/2006/relationships');
$image = $resxml->xpath("/r:Relationships/r:Relationship[@Id='rId3']/@Target");
print_r($image);
答案 1 :(得分:0)
我认为你的问题可能是命名空间。 PPTX Relationship files使用命名空间“http://schemas.microsoft.com/package/2005/06/relationships”。但SimpleXmls xpath也是它自己的魔力。如果文件包含命名空间(检查源),则必须为其注册自己的前缀。
$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)
);
输出:
string(24) "http://www.wikipedia.org"
Xpath不知道默认命名空间。没有前缀,您将查找没有任何名称空间的元素。如果未明确加前缀,则属性没有命名空间。
为了完成混淆,请执行PHP函数(SimpleXMLElement :: xpath(),DOMXpath :: query()和DOMXpath :: evaluate())自动注册已使用上下文的名称空间定义。第三个参数允许禁用该行为。
与其他两个函数不同,DOMXpath :: evaluate()可以直接返回标量。