我目前正在尝试获取一个简单的XML表的数据,该表包含用于翻译的数据,其结构如下:
<string name="action_settings">Settings</string><!-- Comment1 -->
<string name="action_error">Something went wrong.</string>
<string name="action_menu">You've got the choice</string><!-- Comment2 -->
有时,后面会有一些评论,为译者描述更多的内容。我想得到这些,虽然我设法写了一条评论,但我没能得到一条可靠的评论。。。
我的想法是:例如,如果我想得到一个"action_setting"的注释,我会使用xpath来选择这个区域:
<string name="action_settings">Settings</string>|AREASTART|<!-- Comment1 -->
|AREAEND|<string name="action_error">Something went wrong.</string>
<string name="action_menu">You've got the choice</string><!-- Comment2 -->
我已经试着用这个代码归档了:
<?php
$doc = new DOMDocument();
$doc->load('strings.xml');
$xpath = new DOMXPath($doc);
//foreach ($xpath->query("//string[@name='debug']/following::comment()[1]") as $comment)
foreach ($xpath->query("/*/string[count(preceding-sibling::string[@name='debug'])=1]/comment()[1]") as $comment)
{
var_dump($comment->textContent." ");
}
?>
正如您所看到的,注释行只是选择我的特定元素之后的每个注释节点,并选择行中的第一个。这样做的问题是,我不能确保注释真的在特定元素之后,或者仅仅在几行之后的某个元素的注释之后。(所以,如果我想得到"action_error",它会给我属于"action_menu"的"Comment 2"(
正如你所看到的,我已经尝试过选择这个想要的区域,但当有评论时,它根本不会返回任何内容。(我的来源:XPath选择两个特定元素之间的所有元素(
因此,如果你能向我解释我面临的这个问题的解决方案,并在两个特定元素之间发表评论,我将不胜感激。
您可以将following-sibling
与谓词结合使用。
获取下一条评论的文本
(following-sibling::string|following-sibling::comment())[1][self::comment()]
给定上下文节点,例如具有action_settings
:的name
的string
(following-sibling::string|following-sibling::comment())
选择上下文后面的所有
string
和注释同级节点。[1]
过滤节点集以使所有节点的
position()
为1
:换句话说,它将该集缩减为仅第一个节点。[self::comment()]
过滤节点集,使其仅具有注释节点。
总之,上面将返回一个节点集,该节点集由以下任一部分组成:
- 单个评论节点;我们感兴趣的那个
- 一个空的节点集
将其用于示例
<?php
$xml = <<<XML
<example>
<string name="action_settings">Settings</string><!-- Comment1 -->
<string name="action_error">Error</string>
<string name="action_menu">Menu</string><!-- Comment2 -->
</example>
XML;
$doc = new DOMDocument();
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
$next_comment_xpath = 'normalize-space(
(following-sibling::string|following-sibling::comment())[1][self::comment()]
)';
$strings = $xpath->query('//string');
foreach ($strings as $string)
{
$name = $string->getAttribute('name');
$value = $string->nodeValue;
$comment = $xpath->evaluate($next_comment_xpath, $string);
echo "Name: {$name}'n";
echo "Value: {$value}'n";
echo "Comment: {$comment }'n'n";
}
实际工作由$next_comment_xpath
完成,它使用上面给出的示例位置路径。normalize-space()
用于将节点集强制转换为字符串,原因有两个:首先,强制转换为一个字符串可以获得集合中第一个节点的文本内容,如果没有,则为空字符串;其次,这意味着evaluate()
可以返回PHP字符串。
示例输出
Name: action_settings
Value: Settings
Comment: Comment1
Name: action_error
Value: Error
Comment:
Name: action_menu
Value: Menu
Comment: Comment2