Текст вложенного списка маркеров в HTML
У меня есть это: Пример ввода:
* First item
* Second item
* Subitem 1
* sub-subitem!
* Subitem 3
* Third item
Пример вывода:
<ul>
<li>First item</li>
<li>Second item
<ul>
<li>Subitem 1
<ul>
<li>sub-subitem!</li>
</ul>
</li>
<li>Subitem 3</li>
</ul>
</li>
<li>Third item</li>
</ul>
Я создал класс Java, который отправляет каждую строку String в массив символов, и я обрабатываю каждый символ отдельно. Моя проблема в том, когда закрывать теги. Есть идеи?
Вот мой код:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TextToHtml {
StringBuilder itemName = new StringBuilder();
String sCurrentLine;
int usingUlTAG=0;
public TextToHtml(){
BufferedReader br = null;
try {
boolean closeLItag=false;
br = new BufferedReader(new FileReader("NestedText.txt"));
System.out.println("<ul>");
while ((sCurrentLine = br.readLine()) != null) {
char[] item = sCurrentLine.toCharArray();
for(int i=0; i<item.length;i++){
if(item[i]!='*' && item[i]!='\n' && item[i]!='\t'){
itemName.append(item[i]);
continue;
}
if(item[i]=='*'){
itemName.append("<li>");
closeLItag=true;
}
else if(item[i]=='\t'){
if(item[i+1]=='*'){
if(usingUlTAG<1)
itemName.append("\t<ul>\n\t\t");
itemName.append("\t\n\t\t");
usingUlTAG= 1;
continue;
}
if(item[i+1]=='\t'){
itemName.append("\t\t<ul>\n\n\t\t");
usingUlTAG=2;
continue;
}
}
}
if(closeLItag){
itemName.append("</li>\n");
}
}
System.out.println(itemName+"/ul>");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static void main(String[] args) {
new TextToHtml();
}
}
3 ответа
Вам придется заглянуть в следующую строку и посмотреть, отличается ли уровень списка от текущего элемента. Затем вы можете добавить или закрыть теги на основе разницы в уровне, если таковые имеются. Вот код, который делает это:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TextToHtml
{
StringBuilder itemName = new StringBuilder();
String sCurrentLine;
String sNextLine; // A "peek" at what's next to determine if </li> is needed
public TextToHtml()
{
BufferedReader br = null;
try
{
br = new BufferedReader(new FileReader("NestedText.txt"));
System.out.println("<ul>");
sNextLine = br.readLine();
while ((sCurrentLine = sNextLine) != null)
{
sNextLine = br.readLine();
char[] item = sCurrentLine.toCharArray();
int itemLevel = 0;
for (int i = 0; i < item.length; i++)
{
if (item[i] != '*' && item[i] != '\n' && item[i] != '\t')
{
itemName.append(item[i]);
}
else if (item[i] == '*')
{
itemName.append("\t<li>");
// Trim leading space character
if (item[i + 1] == ' ')
i++;
}
else if (item[i] == '\t')
{
itemLevel++;
itemName.append("\t\t");
}
}
int nextItemLevel = 0;
if (sNextLine != null)
{
char[] nextItem = sNextLine.toCharArray();
for (int i = 0; i < nextItem.length; i++)
{
if (nextItem[i] == '\t')
nextItemLevel++;
else
break;
}
}
// Next is the same level; there are no subitems
if (itemLevel == nextItemLevel)
itemName.append("</li>");
// Next is a deeper level; there are subitems
else if (itemLevel < nextItemLevel)
{
// In case the next item is more than 1 level deeper
for (int i = itemLevel + 1; i <= nextItemLevel; i++)
{
itemName.append("\n");
for (int j = 0; j < i; j++)
itemName.append("\t\t");
itemName.append("<ul>");
// If the next item's level is reached, it will create its own <li>
if (i != nextItemLevel)
{
itemName.append("\n");
for (int j = 0; j < i; j++)
itemName.append("\t\t");
itemName.append("\t<li>");
}
}
}
// Next is a higher level; there are tags to close
else // (itemLevel > nextItemLevel)
{
itemName.append("</li>");
for (int i = itemLevel - 1; i >= nextItemLevel; i--)
{
itemName.append("\n");
for (int j = 0; j <= i; j++)
itemName.append("\t\t");
itemName.append("</ul>\n");
for (int j = 0; j < i; j++)
itemName.append("\t\t");
itemName.append("\t</li>");
}
}
itemName.append("\n");
}
System.out.println(itemName + "</ul>");
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (br != null)
br.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
public static void main(String[] args)
{
new TextToHtml();
}
}
Обратите внимание, что это будет работать только в том случае, если уровни имеют отступы, а не пробелы.
Если, как предполагает ваш текущий код, все строки элементов списка в исходном тексте используют жесткие вкладки для отступа, тогда все, что вам нужно сделать, это работать с текстом по строке за раз, отслеживая уровень отступа (количество вкладок) предыдущей строки. Этот код не производит хороший отступ в результирующий HTML, но он получает <ul>
а также <li>
право вложенности, которое все HTML-браузер действительно заботится
import java.io.*;
import java.util.regex.*;
public class Main {
public static void main(String[] args) throws Exception {
StringBuilder result = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader("NestedText.txt"));
try {
int lastIndent = -1; // indent level of last line
int depth = 0; // number of levels of <ul> we are currently inside
String line;
Pattern indentPattern = Pattern.compile("((\\t*)\\* )?(.*)");
while((line = br.readLine()) != null) {
Matcher m = indentPattern.matcher(line);
m.matches(); // guaranteed to be true, but needed to update matcher state
if(m.group(1) != null) { // this is a new list item
int thisIndent = m.end(2); // number of leading tabs, may be zero
// there are three possible cases
if(thisIndent == lastIndent) {
// same level as last list item
result.append("</li>");
} else if(thisIndent > lastIndent) {
// starting a child list
result.append("<ul>");
depth++;
} else {
// returning to parent list
result.append("</li>");
depth--;
result.append("</ul>");
result.append("</li>");
}
result.append("<li>");
lastIndent = thisIndent;
} else { // this is a continuation of the previous list item
result.append(" ");
}
// append this line's text (not including the indent and *)
result.append(m.group(3));
}
// run out of items, close any outstanding lists
while(depth-- > 0) {
result.append("</li>");
result.append("</ul>");
}
System.out.println(result);
} finally {
br.close();
}
}
}
Здесь я рассматриваю любую строку, которая не начинается со вкладок и звездочки, как продолжение предыдущего <li>
т.е.
* This is a very long list
item that continues over several
lines
* This is a second item
* this is a child item
that also continues
over several lines
все в порядке.
Я решил проблему, следуя совету Яна Дворака. следующий код работает, и я помещу ниже в случае, если это помогает кому-то еще. Спасибо за ваш вклад
MarkdownProcessor m = new MarkdownProcessor();
String html = null;
try {
html = m.markdown(MyString));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(html);