Tu excelente aporte me ha venido bien para repasar los recursos que tiene Velneo para el parseo de cadenas de texto, tal como los XML, HTML y demás textos estructurados.
He visto que Velneo no contempla algunas funciones importantes para estos menesteres y recordando mi experiencia con otros lenguajes he completado tu aportación con 3 nuevas funciones de JavaScript.
La primera función es cadenaOcurrencias(cCadena, cBuscar, lCaseInsensitive) que nos dirá el número de veces que una cadena se repite dentro de otra.
La segunda es cadenaPosicion(cCadena, cBuscar, nInicio, nOcurrencia) que nos devuelve la posición de la n-ocurrencia de una cadena dentro de otra a partir de una determinada posición.
La tercera es cadenaExtraer(cCadena, cIniLim, cFinLim, nOcurrencia, lCaseInsensitive) que nos devuelve la subcadena entre dos delimitadores dentro de una cadena principal.
Aquí va el código.
/ *****************************************************************
// Función cadenaExtraer(cCadena, cIniLim, cFinLim, nOcurrencia, lCaseInsensitive) -
// Extrae un String entre 2 delimitadores
// cCadena - cadena a analizar
// cIniLim - límite inicial
// cFinLim - límite final
// nOcurrencia - nº de ocurrencia
// lCaseInsensitive - es true para no sensible a mayúsculas
function cadenaExtraer(cCadena, cIniLim, cFinLim, nOcurrencia, lCaseInsensitive){
// Busca la primera ocurrencia en caso de no pasar un valor positivo de nOcurrencia
if (!nOcurrencia) nOcurrencia = 1;
var nPos1, nPos2;
if (lCaseInsensitive) {
var cCadenab = cCadena.toLowerCase();
cIniLim = cIniLim.toLowerCase();
cFinLim = cFinLim.toLowerCase();
}
nPos1 = cadenaPosicion(cCadenab, cIniLim, 0, nOcurrencia)
if (nPos1 > -1){
nPos1 += cIniLim.length;
nPos2 = cadenaPosicion(cCadenab, cFinLim, nPos1, 1);
}
if(nPos1 > -1 && nPos2 > -1) {
return cCadena.substring(nPos1, nPos2);
} else {
return "";
}
}
// *****************************************************************
// Función CadenaOcurrencias(cCadena, cBuscar, lCaseInsensitive) -
// Devuelve el Nº de ocurrencias de cBuscar en cCadena
// cCadena - cadena a analizar
// cBuscar - cadena a buscar
// lCaseInsensitive - es true para no sensible a mayúsculas
function CadenaOcurrencias(cCadena, cBuscar, lCaseInsensitive) {
// Contador de ocurrencias
if (cBuscar.length = 0) return 0;
if (lCaseInsensitive) {
cCadena = cCadena.toLowerCase();
cBuscar = cBuscar.toLowerCase();
}
var contador = 0, inicio = 0, longitud = cBuscar.length;
while((inicio = cCadena.indexOf(cBuscar, inicio)) > -1) {
contador++;
inicio += longitud;
}
return contador.toFixed(0);
}
// *****************************************************************
// Función cadenaPosicion(cCadena, cBuscar, nInicio, nOcurrencia) -
// Devuelve la posición de la N-Ocurrencia de cBuscar en cCadena a partir de una posición inicial
// cCadena - cadena a analizar
// cBuscar - cadena a buscar
// nInicio - inicio de la búsqueda (0 es el inicio)
// nOcurrencia - nº de ocurrencia
function cadenaPosicion(cCadena, cBuscar, nInicio, nOcurrencia) {
// Contador de ocurrencias
var contador = 0, inicio = nInicio, longitud = cBuscar.length;
var result = "";
while((inicio = cCadena.indexOf(cBuscar, inicio)) > -1) {
contador++;
if (contador==nOcurrencia){
return inicio;
}
inicio += longitud;
}
return -1;
}
En el adjunto se ve un ejemplo de uso.
Espero que os sea de ayuda.
He corregido el código para evitar bucles infinitos y dejar un solo return y lo he formateado un poco.
// *****************************************************************
// Función cadenaExtraer(cCadena, cIniLim, cFinLim, nOcurrencia, lCaseInsensitive) -
// Extrae un String entre 2 delimitadores
// cCadena - cadena a analizar
// cIniLim - límite inicial
// cFinLim - límite final
// nOcurrencia - nº de ocurrencia
// lCaseInsensitive - es true para no sensible a mayúsculas
function cadenaExtraer(cCadena, cIniLim, cFinLim, nOcurrencia, lCaseInsensitive) {
// Busca la primera ocurrencia en caso de no pasar un valor positivo de nOcurrencia
if (!nOcurrencia) nOcurrencia = 1;
var nPos1, nPos2, subcadena = "";
if (lCaseInsensitive) {
var cCadenab = cCadena.toLowerCase();
cIniLim = cIniLim.toLowerCase();
cFinLim = cFinLim.toLowerCase();
}
nPos1 = cadenaPosicion(cCadenab, cIniLim, 0, nOcurrencia);
if (nPos1 > -1) {
nPos1 += cIniLim.length;
nPos2 = cadenaPosicion(cCadenab, cFinLim, nPos1, 1);
}
if (nPos1 > -1 && nPos2 > -1) {
subcadena = cCadena.substring(nPos1, nPos2);
}
return subcadena
}
// *****************************************************************
// Función CadenaOcurrencias(cCadena, cBuscar, lCaseInsensitive) -
// Devuelve el Nº de ocurrencias de cBuscar en cCadena
// cCadena - cadena a analizar
// cBuscar - cadena a buscar
// lCaseInsensitive - es true para no sensible a mayúsculas
function CadenaOcurrencias(cCadena, cBuscar, lCaseInsensitive) {
// Contador de ocurrencias
var contador = 0,
inicio = 0,
longitud = cBuscar.length;
if (longitud && cCadena.length) {
if (lCaseInsensitive) {
cCadena = cCadena.toLowerCase();
cBuscar = cBuscar.toLowerCase();
}
while ((inicio = cCadena.indexOf(cBuscar, inicio)) > -1) {
contador++;
inicio += longitud;
}
}
return contador.toFixed(0);
}
// *****************************************************************
// Función cadenaPosicion(cCadena, cBuscar, nInicio, nOcurrencia) -
// Devuelve la posición de la N-Ocurrencia de cBuscar en cCadena a partir de una posición
// cCadena - cadena a analizar
// cBuscar - cadena a buscar
// nInicio - inicio de la búsqueda (0 es el inicio)
// nOcurrencia - nº de ocurrencia
function cadenaPosicion(cCadena, cBuscar, nInicio, nOcurrencia) {
// Contador de ocurrencias
var contador = 0,
posicion = -1,
longitud = cBuscar.length;
if (longitud && cCadena.length) {
posicion = nInicio
while ((posicion = cCadena.indexOf(cBuscar, posicion)) > -1) {
contador++;
if (contador == nOcurrencia) {
break;
}
posicion += longitud;
}
}
return posicion;
}