如何选择以下节点的字符串内容:
<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个节点
我在php中使用simple_xml,我认为唯一的另一个选择是使用// span返回:
Array
(
[0] => SimpleXMLElement Object
(
[@attributes] => Array
(
[class] => url
)
[b] => test
)
[1] => SimpleXMLElement Object
(
[@attributes] => Array
(
[class] => url
)
[b] => test2
)
)
*请注意,它也会删除第二个范围内的“更多单词”文本。
所以我想我可以使用php在数组中展平项目如何? Xpath是首选,但任何其他想法也会有所帮助。
答案 0 :(得分:4)
$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;
答案 1 :(得分:4)
你甚至不需要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;
而不是替换nodeValue。我知道你想要跨度的一个字符串,而不是嵌套的结构。在这种情况下,您还应该考虑在跨度代码段上运行strip_tags
是否更快更容易。
使用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;
}
答案 2 :(得分:2)
使用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
答案 3 :(得分:1)
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;
}
答案 4 :(得分:0)
//span//text()
这可能是你能做的最好的事情。您将获得多个文本节点,因为文本存储在DOM中的单独节点中。如果你想要一个字符串,你必须自己连接文本节点,因为我想不出一种方法来获得内置的XPath函数。
使用string()
或concat()
将无效,因为这些函数需要字符串参数。将节点集传递给期望字符串的函数时,通过获取节点集中 first 节点的文本内容,将节点集转换为字符串。其余的节点都被丢弃了。
答案 5 :(得分:0)
如何选择字符串内容 以下节点:
首先,我认为你的问题不明确。
您可以选择后代文本节点,如John Kugelman回答
//span//text()
我建议使用绝对路径(不是以//
开头)
但是有了这个,你需要处理从他们是孩子的父span
找到的文本节点。因此,最好只选择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
答案 6 :(得分:0)
沿着亚历杭德罗的XSLT 1.0“,但任何其他想法也会有所帮助”回答......
<强> XML:强>
<?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>
<强> XSL:强>
<?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