我的表格中有数据:
<ol>
<li>example1</li>
<li>example2</li>
<li>example3</li>
</ol>
需要变成
# example1
# example2
# example3
井号必须与ol html标签相关联。我正在使用java正则表达式,这是我到目前为止所做的:
info = info.replaceAll("(?s).<ol>\n(<li>(.*?)</li>\n)*</ol>","# $2");
info是包含数据的字符串对象。 li标签之间也可能有换行符。当我运行它时,它只打印最后一个项目。即结果是
# example3
example2和example1缺失
对我做错了什么的想法?
答案 0 :(得分:1)
你的正则表达式有几个问题:
我建议的解决方案:不要束缚自己。用Matcher.find()编写一个循环,逐个拉出匹配并将它们添加到字符串缓冲区。它会是这样的:
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();
答案 1 :(得分:1)
我认为你可以使用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);
}
}
答案 2 :(得分:0)
编辑:修复hoipolloi提到的<ul>
问题并展望未来:
(?=((?!</ul>)(.|\n))*</ol>)
这个就是你的例子:
info.replaceAll(
"(?:<ol>\s*)?<li>(.*?)</li>(?=((?!</ul>)(.|\n))*</ol>)(?:\s*</ol>)?",
"# $1"
);
修改:添加说明。 (也许有人会改掉他们的投票。)
(?:<ol>\s*)?
<ol>
以及其后的任何空格。 (?:
表示不捕获此组。<li>(.*?)</li>
<li>anything</li>
。并捕获第一组中的anything
。 *?
表示非贪婪地匹配任何长度(即匹配</li>
之后的第一个<li>
。)(?=((?!</ul>)(.|\n))*</ol>)
</ol>
<li>
跟随此</ul>
(?:\s*</ol>)?
</ol>
。答案 3 :(得分:0)
“你做错了什么”的答案是你要用值单个正则表达式(从ol一直到/ ol匹配) >你的第二组。第二组是重复片段,因此$2
的结果是该组的最后一场比赛。
答案 4 :(得分:0)
我会使用更简单的解决方案而不是复杂的正则表达式。例如:
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$
}
答案 5 :(得分:0)
不要使用正则表达式来解析XML / HTML。完全停止。您永远不会处理输入中可能合法发生的所有可能变化,并且您将永远告诉提供您抱歉的内容的人,您只能处理XML的受限子集/ HTML,他们将永远诅咒你。如果你达到了可以处理99%合法输入的程度,那么你的代码将无法维持且速度慢。
有现成的解析器来完成这项工作 - 使用它们。
答案 6 :(得分:0)
info = info.replaceAll("(?:<ol>|\\G)\\s*<li>(.+?)</li>(?:\\s*</ol>)?",
"# $1\n");
(?:<ol>|\G)
确保每一对匹配 在<ol>
元素内。