我的xml结构如下:
<?xml version="1.0" ?>
<users>
<user>
<name>
foo
</name>
<token>
jfhsjfhksdjfhsjkfhksjfsdk
</token>
<connection>
<host>
localhost
</host>
<username>
root
</username>
<dbName>
Test
</dbName>
<dbPass>
123456789
</dbPass>
</connection>
</user>
<user>
... same structure...
</user>
</users>
我制作了遍历所有xml节点的代码:
function getConString($node)
{
$item = file_get_contents($_SERVER['DOCUMENT_ROOT'] . "con");
$nodes = new SimpleXMLElement($item);
$result = $nodes[0];
foreach($result as $item => $value)
{
if($item == "token")
{
return $value->__toString();
}
}
}
我想要实现的是当$ node等于:
jfhsjfhksdjfhsjkfhksjfsdk
连接节点作为数组返回,我怎么能实现呢?
更新
对于那些没有理解的人,我希望如果我插入令牌:jfhsjfhksdjfhsjkfhksjfsdk
,将返回用户与令牌jfhsjfhksdjfhsjkfhksjfsdk
的连接。所以在这种情况下,我想获取connection
节点的所有内容并创建一个连接字符串:
<connection>
<host>
localhost
</host>
<username>
root
</username>
<dbName>
Test
</dbName>
<dbPass>
123456789
</dbPass>
</connection>
答案 0 :(得分:2)
首先,关于XML代码的一些注意事项。我不知道你的真实XML是否完全如上所述格式化,但如果是这样,重要的是要强调XML空格行为与HTML不同:通常没有DTD或XML模式定义,所有空格都是重要的空格,应该保留。此外,使用DTD或XML模式定义,内容中的空白是重要的。
这意味着使用此XML:
<token>
'\n jfhsjfhksdjfhsjkfhksjfsdk\n'
假定值为'jfhsjfhksdjfhsjkfhksjfsdk'
(\ n =换行符),而不是contains()
。
这使得很难在不预先修改xml的情况下使用xPath查找令牌(您可以使用正则表达式)。您可以使用$value->__toString()
xPath语法,但(理论上)它可以返回多个结果。
我不知道您是否已经测试了上面的代码,但是'\n jfhsjfhksdjfhsjkfhksjfsdk\n'
还返回了类似return trim( $value->__toString() );
的内容(它可以根据缩进级别进行更改)。要仅返回标记值,您必须更改以下代码:
<user>
<name>foo</name>
<token>jfhsjfhksdjfhsjkfhksjfsdk</token>
<connection>
<host>localhost</host>
<username>root</username>
<dbName>Test</dbName>
<dbPass>123456789</dbPass>
</connection>
</user>
我的建议是以这种方式改变你的XML:
function getConString( $token )
{
$data = file_get_contents($_SERVER['DOCUMENT_ROOT'] . "con");
$xml = new SimpleXMLElement( $data );
$path = '//users/user/token[text()="'.$token.'"]';
$found = $xml->xpath( $path );
if( ! count( $found ) ) return False;
$node = $found[0]->xpath('parent::*')[0];
return (array) $node->connection;
}
因为这是存储数据的最正确方法:如果XML是由您生成的,那么更改它应该不会太困难。
无论如何,我建议你使用两种不同的功能 - 一种是xPath,另一种是没有。
function getConString( $token )
{
$data = file_get_contents($_SERVER['DOCUMENT_ROOT'] . "con");
$xml = new SimpleXMLElement( $data );
foreach( $xml->user as $user )
{
if( trim($user->token->__toString()) == $token )
{
$retval = array();
foreach( $user->connection[0] as $key => $val )
{ $retval[$key] = trim($val); }
return $retval;
}
}
return False;
}
$user = getConString( 'jfhsjfhksdjfhsjkfhksjfsdk' );
mysqli_connect ( $user['host'], $user['username'], $user['dbPass'], $user['dbName'] );
在评论中,您会问:“可以将连接节点(例如主机,dbName等)分开并将其保存在特定变量中吗?”
我不明白他们可以创建这种语法的问题:
$user = getConString( 'jfhsjfhksdjfhsjkfhksjfsdk' );
foreach( $user as $key => $val ) $$key = $val;
mysqli_connect ( $host, $username, $dbPass, $dbName );
顺便说一句,你可以用这种方式将返回值放在单独的变量中:
(...)
$retval = array();
foreach( $user->connection[0] as $key => $val )
{ $retval[] = trim($val); }
(...)
或 - 如果您需要特定的变量名称 - 以这种方式更改上面的第二个函数:
list( $dbHost, $dbUser, $dbDb, $dbPass ) = getConString( 'jfhsjfhksdjfhsjkfhksjfsdk' );
mysqli_connect ( $dbHost, $dbUser, $dbPass, $dbDb );
然后以这种方式调用它:
list
您可以使用首选名称更改list
内的变量名称。功能修改是必要的,因为{{1}}
不适用于关联数组。
答案 1 :(得分:1)
假设您不反对使用DOMDocument
而不是simpleXML
,那么您应该能够使用以下内容。如果没有,您必须使用simpleXML
,可以移植XPath查询以与simplexml->xpath
一起使用
$strxml='<?xml version="1.0" ?>
<users>
<user>
<name>
foo
</name>
<token>
jfhsjfhksdjfhsjkfhksjfsdk
</token>
<connection>
<host>
localhost
</host>
<username>
root
</username>
<dbName>
Test
</dbName>
<dbPass>
123456789
</dbPass>
</connection>
</user>
<user>
... same structure...
</user>
</users>';
/* an array to store details of connection */
$conndetails=array();
/* The particular value to be searched for in token nodes */
$var='jfhsjfhksdjfhsjkfhksjfsdk';
/* create the DOM objects & load xml source */
$dom=new DOMDocument;
$dom->loadXML( $strxml );
$xp=new DOMXPath( $dom );
/* Run the query to find the token with particular value - then it's next sibling */
$results=$xp->query('//token[contains( text(), "'.$var.'" )]/following-sibling::connection');
if( $results ){/* iterate through childnodes and store details in array */
foreach( $results as $node ) {
foreach( $node->childNodes as $child ) if( $child->nodeType==XML_ELEMENT_NODE ) $conndetails[ $child->tagName ]=$child->nodeValue;
}
}
print_r( $conndetails );
答案 2 :(得分:1)
您可以将其中一个选项添加到函数中,但是您应该能够理解如何执行此操作,并查看此代码。这将向您展示如何检索所需的信息。
选项1:
# using iteration
$data = new SimpleXMLElement($xml);
foreach ($data->item as $item){
if ($item->user->token == 'jfhsjfhksdjfhsjkfhksjfsdk')
{
echo "host: " . $item->user->connection->host . "<br />";
echo "username: " . $item->user->connection->username . "<br />";
echo "dbName: " . $item->user->connection->dbName . "<br />";
echo "dbPass: " . $item->user->connection->dbPass . "<br />";
} else { continue; }
}
选项2:
# using xpath
$data = new SimpleXMLElement($xml);
// Here we find the element token = jfhsjfhksdjfhsjkfhksjfsdk and get it's parent
$nodes = $data->xpath('//users/user/token[.="jfhsjfhksdjfhsjkfhksjfsdk"]/parent::*');
$user = $nodes[0];
echo "host: " . $user->connection->host . "<br />";
echo "username: " . $user->connection->username . "<br />";
echo "dbName: " . $user->connection->dbName . "<br />";
echo "dbPass: " . $user->connection->dbPass . "<br />";