无法使用 xpath 访问 XML 节点(命名空间问题?)

Can't access XML node using xpath (namepace issue?)

我有一小部分 xml 从名为 tridion 的 cms 导出,我想使用 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>

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

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

更新...

对于url...

$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");

您错过了为正确的命名空间注册别名。这是命名空间 uuid:D612E2C9-CD2E-4CD8-9FAE-3826311343A8 的元素 externallink 的命名空间定义。 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() 将第一个匹配的节点转换为字符串并 return 它:

$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() 只能 return 节点列表,DOMXpath::evaluate() 也可以 return 标量值。

对于 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"