无法使用xpath访问XML节点(名称问题)?

时间:2018-08-23 09:27:33

标签: php dom xpath tridion

我从一个叫做Tridion的cms导出的xml中有一小部分,我想使用php解析此信息。

我尝试使用DOMDocumentDOMXPath访问数据,但是未能检索到所需的信息。

例如,当我尝试从示例数据访问节点 title 时,没有任何结果。

$xmlDoc = new DOMDocument();
$xmlDoc->load($xmlFilePath);

$xpath = new DOMXPath($xmlDoc);
$xpath->registerNamespace('tcm', 'http://www.tridion.com/ContentManager/5.0');
$xpath->registerNamespace('xmlns', 'http://www.w3.org/1999/xlink');
$result = $xpath->query('title');

我相信这是一个名称空间问题,但我不太了解如何处理。

这是导出文件的样子(为了可读性有所缩短):

<PackageItem xmlns:tcm="http://www.tridion.com/ContentManager/5.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.sdltridion.com/ContentManager/ImportExport/Package/2013">
  <PrimaryBlueprintParentUrl>/webdav/Content%20%28en%29/Content/120_external%20Links/Services/EL_www%2some-domin%2Ecom.xml</PrimaryBlueprintParentUrl>
  <Data>
    <tcm:Data>
      <tcm:Title>EL_www.some-domain.com</tcm:Title>
      <tcm:Type>Normal</tcm:Type>
      <tcm:Schema xlink:type="simple" xlink:title="External Link (EL)" xlink:href="/webdav/Content/System/Schemas/Common/External%20Link%20%28EL%29.xsd" IsMandatory="false" />
      <tcm:Content>
        <externallink xmlns="uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8">
          <title>www.some-domain.com</title>
          <url xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.some-domain.com" />
        </externallink>
      </tcm:Content>
    </tcm:Data>
  </Data>
</PackageItem>

2 个答案:

答案 0 :(得分:1)

之前的<externallink>元素为其定义了默认名称空间,而<title>元素为xmlns="uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8"。因此,如果您定义此命名空间(我只使用一个虚拟的-d),然后在您的表达式中使用它...

$xpath->registerNamespace('d', "uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8");
$result = $xpath->query('//d:title');

更新...

对于网址...

$result = $xpath->query('//d:url');

echo $xmlDoc->saveXML($result[0]);

给......

<url xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.some-domain.com"/>

因为它没有这样的值(我刚刚说过要输出找到的第一个节点的XML),所以不确定您需要什么。

如果只需要href属性...

echo $result[0]->getAttribute("xlink:href");

答案 1 :(得分:1)

您错过了为正确的名称空间注册别名的操作。这是命名空间externallink在元素uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8上的命名空间定义。 XML解析器将那个节点理解为{uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8}externallink,并将title子元素理解为{uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8}title。以下3个示例全部都解析为一个title节点,像这样:

  • <title xmlns="uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8"/>
  • <t:title xmlns:t="uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8"/>
  • <el:title xmlns:el="uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8"/>

通过在DOMXpath实例上注册别名,您允许它对表达式执行相同的操作。

$xpath->registerNamespace('e', 'uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8');

e:title-> {uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8}title

Xpath 1.0没有默认的名称空间,因此您必须为要在表达式中使用的任何名称空间注册一个别名。

但是e:title仅查找子节点。要查看文档中的任何节点,请使用//e:title。开头的/将表达式锚定到文档本身(而不是当前上下文节点)。第二个/将轴从child更改为descendant。 使用string()将第一个匹配的节点转换为字符串并返回:

$xpath = new DOMXPath($xmlDoc);
$xpath->registerNamespace('e', 'uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8');
var_dump($xpath->evaluate('string(//e:title)'));

输出:

string(19) "www.some-domain.com"

DOMXpath::query()仅可以返回节点列表,DOMXpath::evaluate()也可以返回标量值。

对于xlink:href属性,您还需要注册该名称空间:

$xpath = new DOMXPath($xmlDoc);
$xpath->registerNamespace('e', 'uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8');
$xpath->registerNamespace('xlink', 'http://www.w3.org/1999/xlink');
var_dump($xpath->evaluate('string(//e:url/@xlink:href)'));

输出:

string(26) "http://www.some-domain.com"