无法使用 xpath 访问 XML 节点(命名空间问题?)
Can't access XML node using xpath (namepace issue?)
我有一小部分 xml 从名为 tridion 的 cms 导出,我想使用 php.
解析此信息
我尝试使用 DOMDocument
和 DOMXPath
访问数据,但未能检索到所需的信息。
例如,当我尝试从我的示例数据访问节点 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"
我有一小部分 xml 从名为 tridion 的 cms 导出,我想使用 php.
解析此信息我尝试使用 DOMDocument
和 DOMXPath
访问数据,但未能检索到所需的信息。
例如,当我尝试从我的示例数据访问节点 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"