Php 在查询所有子节点时,如何确定遍历的XPath?

Php 在查询所有子节点时,如何确定遍历的XPath?,php,xml,xslt,xpath,Php,Xml,Xslt,Xpath,我有一个表示目录结构的XML文档。目录表示为,文件表示为 例如: <xml> <home> <mysite> <www> <images> <file name="logo.gif"/> </images> &l

我有一个表示目录结构的XML文档。目录表示为
,文件表示为

例如:

<xml> <home> <mysite> <www> <images> <file name="logo.gif"/> </images> <file name="index.html"/> <file name="about_us.html"/> </www> </mysite> </home> </xml>
我想运行一个XPath查询来获取所有
节点,但我还想知道每个文件的目录路径(即每个父节点的标记名)-是否有一种简单的方法可以使用XPath实现这一点,或者在我用PHP解析XML树之后是否需要递归遍历它

   //file/concat(string-join(ancestor::*[parent::*]
                                   /concat(name(.), '/'),
                            ''),
                 @name, '&#xA;'
                 )
<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
<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, '&#xA;')"/>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>
home/mysite/www/images/logo.gif
home/mysite/www/index.html
home/mysite/www/about_us.html
根据提供的XML文档进行评估时

   //file/concat(string-join(ancestor::*[parent::*]
                                   /concat(name(.), '/'),
                            ''),
                 @name, '&#xA;'
                 )
<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
<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, '&#xA;')"/>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>
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解决方案

   //file/concat(string-join(ancestor::*[parent::*]
                                   /concat(name(.), '/'),
                            ''),
                 @name, '&#xA;'
                 )
<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
<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, '&#xA;')"/>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>
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'));

}

好问题,+1。有关一行Xpath 2.0解决方案和简单XSLT 1.0解决方案,请参见我的答案。:)