Como premisa, tengo un texto HTML, con algunos <ol>
elementos. Estos tienen un start
atributo, 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.
Desde Java 9, hay un Matcher.replaceAll
mé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 repeat
la 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, result
es:
<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 replaceAll
para 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));
}