[英]How do I account for missing xPaths and keep my data uniform when scraping a website using DOMXPath query method?
[英]How do I determine the XPaths traversed when I query all child nodes?
我有一个表示目录结构的XML文档。 目录表示为<directory_name>
,文件表示为<file name="my_file.txt"/>
。
例如:
<xml> <home> <mysite> <www> <images> <file name="logo.gif"/> </images> <file name="index.html"/> <file name="about_us.html"/> </www> </mysite> </home> </xml>
我想运行一个XPath查询来获取所有<file>
节点,但我也想知道每个文件的目录路径(即每个父节点的标记名称) - 是否有一种简单的方法可以用XPath执行此操作,或者将在PHP中解析后,我需要对XML树进行递归遍历吗?
以下XPath 2.0表达式 :
//file/concat(string-join(ancestor::*[parent::*]
/concat(name(.), '/'),
''),
@name, '
'
)
根据提供的XML文档进行评估时 :
<xml>
<home>
<mysite>
<www>
<images>
<file name="logo.gif"/>
</images>
<file name="index.html"/>
<file name="about_us.html"/>
</www>
</mysite>
</home>
</xml>
产生想要的,正确的结果 :
home/mysite/www/images/logo.gif
home/mysite/www/index.html
home/mysite/www/about_us.html
如果您不能使用XPath 2.0,则无法仅使用XPath 1.0表达式生成所需结果 。
然后必须使用托管XPath的编程语言(例如XSLT,C#,php,...)来生成结果。
这是一个XSLT 1.0解决方案 :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="file">
<xsl:for-each select="ancestor::*[parent::*]">
<xsl:value-of select="concat(name(),'/')"/>
</xsl:for-each>
<xsl:value-of select="concat(@name, '
')"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
当此转换应用于同一XML文档时,会产生相同的正确结果 :
home/mysite/www/images/logo.gif
home/mysite/www/index.html
home/mysite/www/about_us.html
你也可以试试这个
<?php
$dom = new DOMDocument();
$dom->loadXML($xml);
$xpath = new DOMXPath($dom);
$arrNodes = $xpath->query('//file');
foreach($arrNodes as $node) {
$tmpNode = $node->parentNode;
$arrPath = array();
while ($tmpNode->parentNode) {
$arrPath[] = $tmpNode->tagName;
$tmpNode = $tmpNode->parentNode;
}
unset($arrPath[count($arrPath)-1]);
printf('%s/%s<BR>',implode('/',array_reverse($arrPath)),$node->getAttribute('name'));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.