在两个特定元素之间进行选择以获得关闭和开始标记之间的注释
I'm currently trying to fetch the data of a simple XML-Sheet which contains data for translation use it's structured like this:
<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 -->
Sometimes there are comments after to describe the content a bit more for the translator. I'd like to get those, while I managed to write a comment, I couldn't manage to get 1 comment reliable ...
My idea is: If I want to get a comment of "action_setting" for example I use xpath to select this area:
<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 -->
I already tried archieving this with this code:
<?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." ");
}
?>
As you can see the commented line is simply selecting every comment node after my specific element and picks the first one in row. The problem with this is that I can't make sure that the comment is really after the specific element or just the comment of an element a few lines later.(so if I'd like to get "action_error" it would give me "Comment 2" which belongs to "action_menu)
As you can see I tried already to select this desired area but it simply doesn't return anything when there's a comment.(My source: XPath select all elements between two specific elements)
So I'd be grateful if you would explain me a solution for this problem I'm facing with comments between 2 specific elements.
我目前正在尝试获取一个简单的XML-Sheet的数据,其中包含用于翻译的数据,它的结构类似于 这个: p>
&lt; string name =“action_settings”&gt;设置&lt; / string&gt;&lt;! - Comment1 - &gt;
&lt; string name =“action_error” &gt;出了点问题。&lt; / string&gt;
&lt; string name =“action_menu”&gt;您可以选择&lt; / string&gt;&lt;! - Comment2 - &gt;
code> pre>
有时候会有一些评论来为翻译者描述一些内容。
我想得到那些,而我设法写评论,我无法得到1 评论可靠... p>
我的想法是:
如果我想获得“action_setting”的评论,例如我使用xpath来选择这个区域: p>
&lt; string name =“action_settings”&gt;设置&lt; / string&gt; | AREASTART |&lt;! - Comment1 - &gt;
| AREAEND |&lt; string name =“action_error”&gt; Something 出错了。&lt; / string&gt;
&lt; string name =“action_ 菜单“&gt;您已经有了选择&lt; / string&gt;&lt;! - Comment2 - &gt;
code> pre>
我已经尝试使用此代码实现此目的: p>
&lt;?php
$ doc = new DOMDocument();
$ doc-&gt; load('strings.xml');
$ xpath = new DOMXPath($ doc);
// foreach($ xpath-&gt; query(“// string [@ name ='debug'] / following :: comment()[1]”)as $ comment )
foreach($ xpath-&gt; query(“/ * / string [count(preceding-sibling :: string [@ name ='debug'])= 1] / comment()[1]”)作为$ comment )
{
var_dump($ comment-&gt; textContent。“”);
}
?&gt;
code> pre>
正如您所看到的评论 line只是在我的特定元素之后选择每个注释节点并选择行中的第一个。 这个问题是我无法确定评论是否真的在特定元素之后,或者只是几行之后的元素评论。(所以如果我想得到“action_error”它会给我“ 评论2“属于”action_menu“ p>
正如你所看到的,我已经尝试选择这个想要的区域,但是当有评论时它根本不会返回任何内容。(我的来源: XPath选择两个特定元素之间的所有元素) p>
所以,如果您能解释我遇到的这个问题的解决方案,我将不胜感激,我将面对2个特定元素之间的评论。 p>
div>
You could use following-sibling
in conjunction with a predicate.
Get the text of the next comment
(following-sibling::string|following-sibling::comment())[1][self::comment()]
Given a context node, for example the string
with the name
of action_settings
:
-
(following-sibling::string|following-sibling::comment())
Selects all of the
string
and comment sibling nodes following the context. -
[1]
Filters the node set to have all of the nodes'
position()
is1
: in other words, it reduces the set to only the first node. -
[self::comment()]
Filters the node set to have only comment nodes.
In summary, the above will return a node set consisting of either:
- A single comment node; the one we are interested in.
- An empty node set.
Putting it to use in an example
<?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}
";
echo "Value: {$value}
";
echo "Comment: {$comment }
";
}
The real work is done by $next_comment_xpath
which uses the example location path given above. The normalize-space()
is used two cast the node set to a string, for two reasons: firstly, casting to a string gets us the text content of the first node in the set, or an empty string if none and, secondly, it means evaluate()
can return a PHP string.
Example output
Name: action_settings
Value: Settings
Comment: Comment1
Name: action_error
Value: Error
Comment:
Name: action_menu
Value: Menu
Comment: Comment2