мой 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>
Прежде всего, некоторые соображения относительно вашего XML-кода. Я не знаю, отформатирован ли ваш настоящий XML, как указано выше, но если это так, важно подчеркнуть, что поведение XML-пробелов отличается от HTML: обычно без определения схемы DTD или XML, все пробелы являются значительными пробелами и должны быть сохранены , Также с определениями схемы DTD или XML пробелы в содержании значительны .
Это означает, что с помощью этого XML:
<token> jfhsjfhksdjfhsjkfhksjfsdk </token>
<token>
принять значение '\n jfhsjfhksdjfhsjkfhksjfsdk\n'
(\ n = разрыв строки) вместо 'jfhsjfhksdjfhsjkfhksjfsdk'
.
Это затрудняет поиск маркера с помощью xPath без предварительного изменения xml (для него вы можете использовать регулярное выражение). Вы можете использовать синтаксис contains()
xPath для этого, но (теоретически) он может вернуть более одного результата.
Я не знаю, протестировал ли ваш код выше, но также и в том, что $value->__toString()
возвращает что-то вроде '\n jfhsjfhksdjfhsjkfhksjfsdk\n'
(он может меняться в зависимости от уровня отступа). Чтобы вернуть только значение токена, вам необходимо изменить код:
return trim( $value->__toString() );
Мой совет заключается в том, чтобы изменить ваш XML следующим образом:
<user> <name>foo</name> <token>jfhsjfhksdjfhsjkfhksjfsdk</token> <connection> <host>localhost</host> <username>root</username> <dbName>Test</dbName> <dbPass>123456789</dbPass> </connection> </user>
потому что это самый правильный способ хранения данных: если XML создается вами, изменить его не должно быть слишком сложно.
Во всяком случае, я предлагаю вам две разные функции: одну с xPath, без которой.
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; }
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; }
В комментариях вы спрашиваете: «возможно ли взять узел соединения, такой как host, dbName ect … отдельно и сохранить его в определенной переменной»?
Я не понимаю, какие проблемы они могут создать для этого синтаксиса:
$user = getConString( 'jfhsjfhksdjfhsjkfhksjfsdk' ); mysqli_connect ( $user['host'], $user['username'], $user['dbPass'], $user['dbName'] );
BTW, вы можете поместить возвращаемое значение в отдельные переменные следующим образом:
$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
не работает с ассоциативными массивами.
Предполагая, что вы не прочь использовать 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 );
Вы можете сделать один из этих вариантов функцией, но вы должны понимать, как это сделать, видя этот код. Это покажет вам, как получить нужную информацию.
Опция 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 />";