Expresiones regulares: cómo sustituir una cadena con n ocurrencias de una subcadena

Andrea:

Como premisa, tengo un texto HTML, con algunos <ol>elementos. Estos tienen un startatributo, pero el marco que estoy usando no es capaz de interpretarlas durante una conversión de PDF. Por lo tanto, el truco que estoy tratando de aplicar es añadir un número de invisibles <li>elementos al principio.

A modo de ejemplo, supongamos que este texto de entrada:

<ol start="3">
   <li>Element 1</li>
   <li>Element 2</li>
   <li>Element 3</li>
</ol>

Quiero producir este resultado:

<ol>
   <li style="visibility:hidden"></li>
   <li style="visibility:hidden"></li>
   <li>Element 1</li>
   <li>Element 2</li>
   <li>Element 3</li>
</ol>

Por lo tanto, la adición de n-1 elementos invisibles en la lista ordenada. Pero no soy capaz de hacer eso desde Java de una manera generalizada.

Suponiendo que el caso exacto en el ejemplo, podría hacer esto (utilizando replace, por lo que - para ser honesto - y sin expresiones regulares):

htmlString = htmlString.replace("<ol start=\"3\">",
            "<ol><li style=\"visibility:hidden\"></li><li style=\"visibility:hidden\"></li>");

Pero, obviamente, sólo se aplica al caso de "start = 3". Sé que puedo usar grupos para extraer el "3", pero ¿cómo puedo usarlo como una "variable" para especificar la cadena <li style=\"visibility:hidden\"></li>n-1 Número de veces? Gracias por cualquier idea.

tobias_k:

Desde Java 9, hay un Matcher.replaceAllmétodo que tenga una función de devolución de llamada como parámetro:

String text = "<ol start=\"3\">\n\t<li>Element 1</li>\n\t<li>Element 2</li>\n\t<li>Element 3</li>\n</ol>";

String result = Pattern
        .compile("<ol start=\"(\\d)\">")
        .matcher(text)
        .replaceAll(m -> "<ol>" + repeat("\n\t<li style=\"visibility:hidden\" />", 
                                         Integer.parseInt(m.group(1))-1));      

Para repeatla cadena que puede tomar el truco desde aquí , o utilizar un bucle.

public static String repeat(String s, int n) {
    return new String(new char[n]).replace("\0", s);
}

Después, resultes:

<ol>
    <li style="visibility:hidden" />
    <li style="visibility:hidden" />
    <li>Element 1</li>
    <li>Element 2</li>
    <li>Element 3</li>
</ol>   

Si le pegan con una versión anterior de Java, todavía se puede igualar y vuelva a colocar en dos pasos.

Matcher m = Pattern.compile("<ol start=\"(\\d)\">").matcher(text);
while (m.find()) {
    int n = Integer.parseInt(m.group(1));
    text = text.replace("<ol start=\"" + n + "\">", 
            "<ol>" + repeat("\n\t<li style=\"visibility:hidden\" />", n-1));
}

Actualizar por Andrea Gee té O:

He modificado la solución (gran) por encima de la inclusión también <ol>de que tiene varios atributos, por lo que su etiqueta no terminan con start(ejemplo, <ol>con las letras, como <ol start="4" style="list-style-type: upper-alpha;">). Esto utiliza replaceAllpara tratar con expresiones regulares en su conjunto.

//Take something that starts with "<ol start=", ends with ">", and has a number in between
Matcher m = Pattern.compile("<ol start=\"(\\d)\"(.*?)>").matcher(htmlString);
while (m.find()) {
    int n = Integer.parseInt(m.group(1));
    htmlString = htmlString.replaceAll("(<ol start=\"" + n + "\")(.*?)(>)",
            "<ol $2>" + StringUtils.repeat("\n\t<li style=\"visibility:hidden\" />", n - 1));
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=119982&siteId=1
Recomendado
Clasificación