¿Como extraer cadenas especificas de un perfil wireless xml?

Iniciado por Romualdo23, 24 Abril 2015, 04:45 AM

0 Miembros y 2 Visitantes están viendo este tema.

Romualdo23

Hola amigos.

Tengo una funcion en C que me muestra en consola el perfil wireless que yo le indique, hasta aqui todo bien. El problema esta en que recibo los datos en ese formato:

Código (xml) [Seleccionar]
<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
<name>NombrePerfil</name>
<SSIDConfig>
<SSID>
<hex>75775657685794438794</hex>
<name>NombrePerfil</name>
</SSID>
</SSIDConfig>
<connectionType>ESS</connectionType>
<MSM>
<security>
<authEncryption>
<authentication>WPA2PSK</authentication>
<encryption>AES</encryption>
<useOneX>false</useOneX>
</authEncryption>
<sharedKey>
<keyType>passPhrase</keyType>
<protected>false</protected>
<keyMaterial>1234567890</keyMaterial>
</sharedKey>
<keyIndex>1</keyIndex>
</security>
</MSM>
</WLANProfile>




Entonces necesitaria una funcion que extraiga los datos que hay entre <name> y </name>, <connectionType> y </connectionType> y asi con todos los valores.

Quedaria algo asi en consola:

Nombre del perfil: NombrePerfil
Tipo de conexion: ESS
Aunenicacion: WPA2PSK

etc..

Aclaracion: los datos no los recibo de un archivo, sino del PC, de los perfiles almacenados en la WLAN con esta llamada:

hp = Device->GetProfile(ARRAYSIZE(profBuffer), profBuffer);

He probado con este codigo que vi por inernet, pero se bloquea la aplicacion y se termina (creo que se bloquea porque es codigo de C++ y al tratar de usarlo en C se bloquea, no lo se):


   
Código (cpp) [Seleccionar]
int size = 0;

   wchar_t* Perfil = profBuffer;

   std::string text(Perfil, Perfil + size);

   // define what we're looking for
   std::string begin_text("<name>");
   std::string end_text("</name>");

   // find the start and end of the text we need to extract
   size_t begin_pos = text.find(begin_text) + begin_text.length();
   size_t end_pos = text.find(end_text);

   // create a substring from the positions
   std::string extract = text.substr(begin_pos,end_pos);

   // test that we got the extract
   wprintf(L"\nINFO: Nombre del perfil: ", extract);


Espero que me puedan ayudar. Saludos!!

ivancea96

En primer lugar, size es siempre 0. Tendrás que poner ahí el tamaño de la cadena.

En segundo lugar, pon esta linea en sustitucion de la antigua:
Código (cpp) [Seleccionar]
std::string extract = text.substr(begin_pos,end_pos-begin_pos);

En tercer lugar, en caso de que quieras agarrar todos los datos, tal vez te interese crear un método para leer un xml y guardarlo ordenadamente, eso ya como veas.

Romualdo23

Cita de: ivancea96 en 24 Abril 2015, 11:48 AM
En primer lugar, size es siempre 0. Tendrás que poner ahí el tamaño de la cadena.

¿Como puedo saber que tamaño tiene la cadena?

Cita de: ivancea96 en 24 Abril 2015, 11:48 AMEn segundo lugar, pon esta linea en sustitucion de la antigua:
Código (cpp) [Seleccionar]
std::string extract = text.substr(begin_pos,end_pos-begin_pos);

He reemplazado lo que me has dicho pero sigue colgandose y cerrandose la aplicacion..

Cita de: ivancea96 en 24 Abril 2015, 11:48 AMEn tercer lugar, en caso de que quieras agarrar todos los datos, tal vez te interese crear un método para leer un xml y guardarlo ordenadamente, eso ya como veas.

Si, estuve mirando tambien esa opcion, pero los ejemplos que encontre eran solo para abrir archivos xml y yo en este caso no necesito abrir ningun archivo, ya que los datos los recibo del pc y se almacenan en un buffer..

Gracias por la ayuda.

Romualdo23

#3
¿¿¿ Tan dificil es hacer eso en C ????

Si eso mismo en VB.NET lo hago en 1 minuto con esta funcion...

Código (vbnet) [Seleccionar]

   Dim Cadena As String = XmlProfile
   Dim Delimitador_Ini As String = "<name>"
   Dim Delimitador_Fin As String = "</name>"

   Cadena = Split(Cadena , Delimitador_Ini, , CType(CompareMethod.Text, Microsoft.VisualBasic.CompareMethod))(1)
   Cadena = Split(Cadena , Delimitador_Fin, , CType(CompareMethod.Text, Microsoft.VisualBasic.CompareMethod))(0)

   Label1.Text = "Nombre del perfil: " & Cadena

ivancea96

Lo que tratas de hacer en C++ es ese Split() de VB. No es dificil.

wcslen(cadena) retorna el tamaño de la cadena. Intuyo que si no conoces el tamaño, es porque no lo puedes conseguir mediante las funciones de windows.

Si aun asi no te va, trata de usar wstring en vez de string, ya que estás usando wchar_t

Romualdo23

Nada, no hay forma de hacerlo. Lo dejo ya por imposible porque llevo dos dias con esta tonteria y estoy empezando a ponerme de mala hosia.

ivancea96

No, no es imposible, es sencillo. Busca en que punto se cuelga, y sabrás que error es. Puede ser un out_of_range exception en substr. Tal vez porque no encuentre la cadena. Saca por pantalla begin_pos y end_pos despues de calcularlos, y verás cual puede ser el error.

Romualdo23

#7
¿Puede que el error sea porque "profBuffer" ya este declarado como WCHAR y yo lo estaba declarando mas abajo como wchar_t?

El codigo que muesra el perfil xml completo en consola es el siguiente:

Código (cpp) [Seleccionar]
UINT status = ERROR_SUCCESS;

               WCHAR profBuffer[WPA_API_MAX_BUFFER_SIZE] = {0};
       HANDLE wlanHandle = 0;
       GUID interfaceGuid = {0};
       DWORD wlanResult = 0;

               status = WlanGetProfile(wlanHandle, &interfaceGuid, 0, profBuffer, NULL, TRUE, NULL, &wlanResult);

               wprintf(profBuffer);


Con ese codigo obtengo esta salida:



Por otra parte, he probado lo que comentas y nunca recibo ningun valor al comprobar "begin_pos" y "end_pos", es como si no leyera la cadena de texto por algun motivo..

Asi lo estoy haciendo ahora, ya no declaro"profBuffer" como  wchar_t y le he asignado un tamaño a int:

   
Código (cpp) [Seleccionar]


   int size = 2000;

   std::string text(profBuffer, profBuffer + size);

   // define what we're looking for
   std::string begin_text("<name>");
   std::string end_text("</name>");

   // find the start and end of the text we need to extract
   size_t begin_pos = text.find(begin_text) + begin_text.length();
   size_t end_pos = text.find(end_text);

   wprintf(L"\nINFO: begin_pos: ", begin_pos);
   wprintf(L"\nINFO: end_pos: ", end_pos);

   // create a substring from the positions
   std::string extract = text.substr(begin_pos, end_pos);

    //test that we got the extract
    wprintf(L"\nINFO: Nombre del perfil: ", extract);


De esta forma ya no se cuelga, pero tampoco me muestra nada en consola..



Parece que el mtoivo de que se colgara era que antes ponia "int size = 0;", Ahora con "int size = 2000;" ya no se cuelga, pero como digo, parece que no lee la cadena..

ivancea96

wprintf y printf no se utilizan así. http://www.cplusplus.com/reference/cstdio/printf/

Código (cpp) [Seleccionar]
wprintf(L"\nINFO: begin_pos: %u", begin_pos);

En cualqueir caso, y dado que es C++, puedes evitar wprintf utilizando wcout de iostream:

Código (cpp) [Seleccionar]
wcout << endl << L"INFO: begin_pos: " << begin_pos;

Romualdo23