Java正则表达式将HTML列表转换为文本
我有以下表格中的数据:Java正则表达式将HTML列表转换为文本,java,html,xml,regex,Java,Html,Xml,Regex,我有以下表格中的数据: <ol> <li>example1</li> <li>example2</li> <li>example3</li> </ol> 磅符号必须与ol html标记相关联。我正在使用java正则表达式,到目前为止,我已经做到了: info = info.replaceAll("(?s).<ol>\n(<li>(.*?)</li>\n)*<
<ol>
<li>example1</li>
<li>example2</li>
<li>example3</li>
</ol>
磅符号必须与ol html标记相关联。我正在使用java正则表达式,到目前为止,我已经做到了:
info = info.replaceAll("(?s).<ol>\n(<li>(.*?)</li>\n)*</ol>","# $2");
缺少示例2和示例1
关于我做错了什么有什么想法吗?编辑:修复hoipolloi提到的具有前瞻性的
问题:
(?=((?!</ul>)(.|\n))*</ol>)
(?=((?!)(.|\n))*)
这一个对您的示例有效:
info.replaceAll(
"(?:<ol>\s*)?<li>(.*?)</li>(?=((?!</ul>)(.|\n))*</ol>)(?:\s*</ol>)?",
"# $1"
);
info.replaceAll(
“(?:\s*)?(*?) (?=((?!)(.\n))*)(?:\s*)”,
"# $1"
);
编辑:添加解释。(也许有人会推翻他们的否决票。)
(?:\s*)?
- 如果它存在,则匹配
以及它后面的任何空格。
表示不捕获此组(?:
(.*)
- 匹配
- 任何内容
。并在第一组中捕获任何内容
。*?
表示不贪婪地匹配任何长度(即在之后匹配第一个
)
(?=((?!)(.\n))*)
- 确保
在
(?:\s*)?
- 并匹配任何尾随空格加上
“您做错了什么”的答案是,您正在用第二组的值替换整个单个正则表达式(从ol一直匹配到/ol)。第二组是重复的片段,因此,
$2
的结果是该组的最后一个匹配。您的正则表达式有几个问题:
- 它在捕获组中包含一个捕获组
- 总的来说,它只会匹配一次(它包括一个开始——其中只有一个)
Pattern p = Pattern.compile("<ol>(.*?)</ol>");
Matcher m = p.matcher("...");
StringBuffer sb = new StringBuffer();
while (m.find()) {
sb.append("#").append(m.group(1)).append("\n");
}
String result = sb.toString();
Pattern p=Pattern.compile((*?);
匹配器m=p.Matcher(“…”);
StringBuffer sb=新的StringBuffer();
while(m.find()){
附加(m.group(1))。附加(“\n”);
}
字符串结果=sb.toString();
我认为您可以使用XPath和Java的文档解析器实现更健壮的解决方案,如下所示:
import java.io.ByteArrayInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Foo {
public static void main(String[] args) throws Exception {
final String info = "<html>\n<body>\n<ol>\n<li>example1</li>\n<li>exmaple2</li>\n<li>example3</li>\n</ol>\n</body>\n</html>";
final Document document = parseDocument(info);
final XPathExpression xPathExpression = getXPathExpression("//ol/li");
final NodeList nodes = (NodeList) xPathExpression.evaluate(document, XPathConstants.NODESET);
// Prints # example1\n# exmaple2\n# example3
for (int i = 0; i < nodes.getLength(); i++) {
final Node liNode = nodes.item(i);
if (liNode.hasChildNodes()) {
System.out.println("# " + liNode.getChildNodes().item(0).getTextContent());
}
}
}
private static Document parseDocument(final String info) throws Exception {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
final DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(info.getBytes("UTF-8")));
}
private static XPathExpression getXPathExpression(final String expression) throws Exception {
final XPathFactory factory = XPathFactory.newInstance();
final XPath xpath = factory.newXPath();
return xpath.compile(expression);
}
}
import java.io.ByteArrayInputStream;
导入javax.xml.parsers.DocumentBuilder;
导入javax.xml.parsers.DocumentBuilderFactory;
导入javax.xml.xpath.xpath;
导入javax.xml.xpath.XPathConstants;
导入javax.xml.xpath.XPathExpression;
导入javax.xml.xpath.XPathFactory;
导入org.w3c.dom.Document;
导入org.w3c.dom.Node;
导入org.w3c.dom.NodeList;
公开课Foo{
公共静态void main(字符串[]args)引发异常{
最终字符串信息=“\n\n示例1 \n示例2 \n示例3 \n\n\n”;
最终文件=解析文件(信息);
final XPathExpression XPathExpression=getXPathExpression(“//ol/li”);
最终节点列表节点=(节点列表)xPathExpression.evaluate(文档,XPathConstants.NODESET);
//打印#示例1\n#示例2\n#示例3
对于(int i=0;i
我会使用更简单的解决方案,而不是复杂的正则表达式。例如:
Scanner scann= new Scanner(str); //the parameter can be a file or an inputstream
scann.useDelimiter("</?ol>");
while (scann.hasNext())
{
str = scann.next();
str = str.replaceAll("<li>(.*?)</li>\n*","# $1" +
"\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
Scanner scann=new Scanner(str);//参数可以是文件或输入流
scann.useDelimiter(“”);
while(scann.hasNext())
{
str=scann.next();
str=str.replaceAll(“(.*) \n*”,“#$1”+
“\n”);//$NON-NLS-1$//$NON-NLS-2$
}
不要使用正则表达式解析XML/HTML。句号。你永远不会处理输入中可能合法出现的所有变化,你将永远告诉提供内容的人你很抱歉,你只能处理XML/HTML的一个受限子集,他们将永远诅咒你。如果你真的这样做了当您可以处理99%的合法输入时,您的代码将无法维护且速度缓慢
有现成的解析器来完成这项工作-使用它们。info=info.replaceAll((?:\\G)\\s*(.+?) (?:\\s*),
info = info.replaceAll("(?:<ol>|\\G)\\s*<li>(.+?)</li>(?:\\s*</ol>)?",
"# $1\n");
“#$1\n”);
(?:|\G)
确保每一组匹配要么从
开始,要么从上次匹配结束的地方开始,因此它永远无法在
元素内开始匹配。这里有许多相关问题的示例。@Nightfirecat-尽管在本例中通常对html和正则表达式进行声明,但它会看到我完全合理。好吧,假设它的格式都正确,它是完全可能的(甚至有些合理),但这仍然不是RegEx的本意。同意,但如果你采用Neil的方法,这是情有可原的。我得说,这很聪明。+1解决这个问题的推理。另一方面,除非代码是虐待狂社会竞赛的参赛作品
Scanner scann= new Scanner(str); //the parameter can be a file or an inputstream
scann.useDelimiter("</?ol>");
while (scann.hasNext())
{
str = scann.next();
str = str.replaceAll("<li>(.*?)</li>\n*","# $1" +
"\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
info = info.replaceAll("(?:<ol>|\\G)\\s*<li>(.+?)</li>(?:\\s*</ol>)?",
"# $1\n");