比 $DOMDocument->getNodePath(); 更具体的路径;

More specific path than $DOMDocument->getNodePath();

我目前需要一个元素的 XPath 路径。路径必须包含唯一标识路径中每个元素的属性(在本例中为名称属性)。

$DOMDocument->getNodePath(); returns 路径,但没有属性。这些属性是必需的,因为 XML 会发生很大变化。

我目前正在编写一种方法来手动遍历并检查路径中的每个元素的名称属性,然后将其插入到字符串中的适当位置。是否有一种 easier/faster/not 作为 hackish 的方式来做到这一点?

您或许可以使用 XPath 获取字符串。例如,在 xsh:

for //address {
    for ancestor-or-self::*
        echo :s :n '/'
                   name()
                   xsh:if(@name, concat('[@name="', @name, '"]'),'') ;
    echo ;
}

在以下 XML

运行它
<root>
  <customers name="2014">
    <customer name="John">
      <address/>
    </customer>
    <customer name="Jane">
      <address/>
    </customer>
    </customers>
    <customers name="2015">
      <customer name="Daniel">
        <address/>
      </customer>
      <customer name="Dave">
        <address/>
      </customer>
    </customers>
</root>

我得到

/root/customers[@name="2014"]/customer[@name="John"]/address
/root/customers[@name="2014"]/customer[@name="Jane"]/address
/root/customers[@name="2015"]/customer[@name="Daniel"]/address
/root/customers[@name="2015"]/customer[@name="Dave"]/address

@choroba 的 xsh 解决方案可以使用 DOMXpath::evaluate() 翻译成 PHP 源代码:

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);

foreach ($xpath->evaluate('//address') as $address) {
  $path = '';  
  foreach ($xpath->evaluate('ancestor-or-self::*', $address) as $ancestor) {
    $path .= '/'.$ancestor->nodeName;
    if ($name = $ancestor->getAttribute('name')) {
      $path .= '[@name = "'.$name.'"]';
    }
  }
  var_dump($path);
}

ancestor-or-self::* 是一个 Xpath 表达式,它获取从上下文节点开始到文档元素的所有元素节点。