首页 文章

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

提问于
浏览
3

我有一个表示目录结构的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树进行递归遍历?

2 回答

  • 0

    The following XPath 2.0 expression

    //file/concat(string-join(ancestor::*[parent::*]
                                       /concat(name(.), '/'),
                                ''),
                     @name, '&#xA;'
                     )
    

    when evaluated against the provided XML document

    <xml>
        <home>
            <mysite>
                <www>
                    <images>
                        <file name="logo.gif"/>
                    </images>
                    <file name="index.html"/>
                    <file name="about_us.html"/>
                </www>
            </mysite>
        </home>
    </xml>
    

    produces the wanted, correct result

    home/mysite/www/images/logo.gif
     home/mysite/www/index.html
     home/mysite/www/about_us.html
    

    In case you cannot use XPath 2.0, it isn't possible to produce the wanted result only with an XPath 1.0 expression .

    然后必须使用托管XPath的编程语言(例如XSLT,C#,php,...)来生成结果 .

    Here is an XSLT 1.0 solution

    <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>
    

    when this transformation is applied on the same XML document, the same correct result is produced

    home/mysite/www/images/logo.gif
    home/mysite/www/index.html
    home/mysite/www/about_us.html
    
  • 2

    你也可以试试这个

    <?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'));
    
    }
    

相关问题