代码之家  ›  专栏  ›  技术社区  ›  spyderman4g63

XPath节点到字符串

  •  2
  • spyderman4g63  · 技术社区  · 14 年前

    如何选择以下节点的字符串内容:

    <span class="url">
     word
     <b class=" ">test</b>
    </span>
    
    <span class="url">
     word
     <b class=" ">test2</b>
     more words
    </span>
    

    我试过一些东西

    //span/text()
    

    //span/string(.)
    

    无效

    string(//span)
    

    仅选择1个节点

    Array
    (
        [0] => SimpleXMLElement Object
            (
                [@attributes] => Array
                    (
                        [class] => url
                    )
    
                [b] => test
            )
    
        [1] => SimpleXMLElement Object
            (
                [@attributes] => Array
                    (
                        [class] => url
                    )
    
                [b] => test2
            )
    
    )
    

    *注意,它还从第二个跨度中删除了“morewords”文本。

    7 回复  |  直到 14 年前
        1
  •  4
  •   Wrikken    14 年前
    $xml = '<foo>
    <span class="url">
     word
     <b class=" ">test</b>
    </span>
    
    <span class="url">
     word
     <b class=" ">test2</b>
     more words
    </span>
    </foo>';
    $dom = new DOMDocument();
    $dom->loadXML($xml); //or load an HTML document with loadHTML()
    $x= new DOMXpath($dom);
    foreach($x->query("//span[@class='url']") as $node) echo $node->textContent;
    
        2
  •  4
  •   Gordon Haim Evgi    14 年前

    您甚至不需要XPath:

    $dom = new DOMDocument;
    $dom->loadHTML($html);
    foreach($dom->getElementsByTagName('span') as $span) {
        if(in_array('url', explode(' ', $span->getAttribute('class')))) {
            $span->nodeValue = $span->textContent;
        }
    }
    echo $dom->saveHTML();
    

    在下面的评论后编辑

    echo $span->textContent; strip_tags 在span代码段上不是更快更容易的选择。


    使用PHP5.3,您还可以注册任意PHP函数,用作XPath查询中的回调。下面将获取所有span元素及其子节点的内容,并将其作为单个字符串返回。

    $dom = new DOMDocument;
    $dom->loadHTML($html);
    $xp = new DOMXPath($dom);
    $xp->registerNamespace("php", "http://php.net/xpath");
    $xp->registerPHPFunctions();
    echo $xp->evaluate('php:function("nodeTextJoin", //span)');
    
    // Custom Callback function
    function nodeTextJoin($nodes)
    {
        $text = '';
        foreach($nodes as $node) {
            $text .= $node->textContent;
        }
        return $text;
    }
    
        3
  •  2
  •   GZipp    14 年前

    使用XMLReader:

    $xmlr = new XMLReader;
    $xmlr->xml($doc);
    while ($xmlr->read()) {
        if (($xmlr->nodeType == XmlReader::ELEMENT) && ($xmlr->name == 'span')) {
            echo $xmlr->readString();
        }
    }
    

    输出:

    word
    test
    
    word
    test2
    more words
    
        4
  •  1
  •   Josh Davis    14 年前

    SimpleXML不喜欢将文本节点与其他元素混合,这就是为什么会丢失一些内容。然而,DOM扩展可以很好地处理这个问题。幸运的是,DOM和SimpleXML是同一个硬币(libxml)的两面,所以很容易处理它们。例如:

    foreach ($yourSimpleXMLElement->xpath('//span') as $span)
    {
        // will not work as expected
        echo $span;
    
        // will work as expected
        echo textContent($span);
    }
    
    function textContent(SimpleXMLElement $node)
    {
        return dom_import_simplexml($node)->textContent;
    }
    
        5
  •  0
  •   John Kugelman Michael Hodel    14 年前
    //span//text()
    

    这也许是你能做的最好的了。您将获得多个文本节点,因为文本存储在DOM中的不同节点中。如果您想要一个字符串,就必须自己连接文本节点,因为我想不出一种方法让内置的XPath函数来实现这一点。

    使用 string() concat() 第一 节点集中的节点。其余节点将被丢弃。

        6
  •  0
  •   user357812 user357812    14 年前

    如何选择字符串内容

    首先,我认为你的问题不清楚。

    你可以的 选择 John Kugelman回答的后代文本节点

    //span//text()
    

    我建议使用绝对路径(不要以 // )

    但是有了它,您将需要处理从哪个父节点查找的文本节点 span 跨度 //span )然后处理它的字符串值。

    使用XPath 2.0,您可以使用:

    string-join(//span, '.')
    

    word test. word test2 more words
    

    在XSLT 1.0中,此输入:

    <div>
    <span class="url">
     word
     <b class=" ">test</b>
    </span>
    
    <span class="url">
     word
     <b class=" ">test2</b>
     more words
    </span>
    </div>
    

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
        <xsl:template match="span[@class='url']">
            <xsl:value-of select="concat(substring('.',1,position()-1),normalize-space(.))"/>
        </xsl:template>
    </xsl:stylesheet>
    

    输出:

    word test.word test2 more words
    
        7
  •  0
  •   Daniel Haley    14 年前

    按照Alejandro的XSLT1.0 但其他的想法也会有帮助 “回答。。。

    <?xml version="1.0" encoding="UTF-8"?>
    <div>
        <span class="url">
            word
            <b class=" ">test</b>
        </span>
        <span class="url">
            word
            <b class=" ">test2</b>
            more words
        </span>
    </div>
    

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
        <xsl:template match="span">
            <xsl:value-of select="normalize-space(data(.))"/>
        </xsl:template>
    </xsl:stylesheet>
    

    输出:

    word test
    word test2 more words