现在假设有一个html文档,如下:
<html>
  <table>
    <tr>
       <td>取这个信息</td>
    <tr>
  </table>
  <table>
    <td>不取这个信息</td>
  </table>
</html>程序要取第一个table,我形成了一个特征码并存在一个文件中,是这样:
<table><tr><td></td><tr></table>,我想分析程序能够根据这个特征码取出第一个table,而不取第二个table,请问该怎样做,正则表达式我想是不行的,因为特征码可能会变成其它的,如div等,顺序和结构也可能会变,譬如:
<html>
  <div>
    <br><a>取这个信息</a>
  </div>
  <div>
    <a>不取这个信息</a>
  </div>
</html>
如果要取第一个div,特征码又变成<div><br><a></a></div>,请问后续的分析程序该怎样方便的根据特征码找到第一个div(如果后面还有一样的结构,也能把它找出来),NekoHTML能行吗,如果行,用它什么方法呢?如果不行,又该怎么办呢?特向各位高手请教!

解决方案 »

  1.   

    如果是标准html,那可以考虑将它放到XML中处理(如dom4j)。
    这样特征码的问题就简化成过滤节点的问题,只要看节点下有没指定的子节点就可以了。
      

  2.   

    标不标准很难说呀,能不能这么做呢:我用tidy针对特征码生成标准的html(尽管我知道它不可能解决所有的问题),用这个标准的html生成特征码。然后在分析程序中先将整个html用tidy标准化,然后再根据特征码定位。
         但这里面隐含着三个问题:
    1、tidy不可能将所有非标准的html变成标准的;
    2、针对特征码生成的标准html可能与分析程序先将整个html标准化后的特征码不一致,这一点不知道我说清楚没有。有人可能会问,你为什么不能在生成特征码的过程中也针对整个html先标准化,然后再生成特征码?原因是这样的,我是先用mshtml的get_selection()和htmlText获得选中部分的源代码的,然后把其中数据的部分去掉得到特征码,所以如果我先把整个html标准化了,那么选中部分的源代码也就消失了。     请大家给予指导!谢谢!
      

  3.   

    getElementsByTagName("Table")
    把所有的table找出来,然后取第一个就可以了,如果有嵌套的时候就比较麻烦。
    innerText可以把内容取出来。
      

  4.   

    to wdman(只提供解决方案,代码另外收分!):这种方法恐怕有些问题,正如我所描述的,特征码是多变的,分析器纯粹是根据配置文件的特征码来分析html文件,按照getElementsByTagName的方式应该是不行的
      

  5.   

    你想实现什么样的效果,比如<table>和<tr>之间还有其它的标签呢,你要怎么处理,是取还是不取。
      

  6.   

    说实话不太清楚你说的特征码和数据的区分。
    你的目的是要取数据吗?
    假设你的特征码是<div><br/><a></a></div>
    文件内容是
    <html>
      <div>
        内容1
        <br/><a>内容2</a>
      </div>
      <div>
        <a>内容3</a>
        <br>内容4
      </div>
    </html>
    这个时候你需要的内容是什么?
      

  7.   

    to wdman(只提供解决方案,代码另外收分!):假设特征码是<div><br/><a></a></div>,我把你的文件内容改为:
    <html>
    <div>内容1<br/><a>内容2</a></div>
    <div><a>内容3</a><br/>内容4</div>
    <div>内容5<br/><a>内容6</a></div>
    </html>
    我想根据特征码,就能够定位到第一个和第三个div,这个定位的工作首先我就不知道怎样做,然后第二步我才要进入到这个块中,具体取相应的数据,比如只取<div>和<br/>之间的数据,如上面的内容,则最终取出的应该是内容1和内容5。总结如下:
    1)第一步,定位数据块,不知道怎样做。
    2)第二步,分别在定位的数据块取出相应的细项数据,也不知道应怎样做。
      

  8.   

    var tables = document.getElmentByTagNames("div");
    for(var i=0;i<tables.length;i++)
    {
       var tableHtml = tables[i].innerHTML;
       //判断tableHtml中有你的取舍标志
    }
      

  9.   

    to qingyuan18(zealot_tang):
    你这样的方法不灵活,不能适应我的设想,原因如下,假设现在有两个html,
    1)<html>
            <div>内容1<br/><a>内容2</a></div>
            <div><a>内容3</a><br/>内容4</div>
            <div>内容5<br/><a>内容6</a></div>
       </html>
       对于这个html,特征码为<div><br/><a></a></div>,也就是我想取第一和第三个div
    2)<html>
            <table><tr><td></td><td></td></tr><tr><td>内容1<td></tr></table>
            <table><tr>内容2<td></td></tr></table>
            <table><tr><td>内容3</td><td></td></tr><tr><td><td></tr></table>
       </html>
       对于这个html,特征码为<table><tr><td></td><td></td></tr><tr><td><td></tr></table>,
       也就是我想取第一和第三个table。
       我的需求是,对于不同的html,如果我能定义出特征码,程序就能够灵活的根据特征码找出与这个特征码匹配的块来,请问该怎样做呢?
      

  10.   

    还是用模式匹配。
    你说的
    1)第一步,定位数据块,不知道怎样做。
    2)第二步,分别在定位的数据块取出相应的细项数据,也不知道应怎样做。第一步用getTargetBlocks函数
    第二步用getTargetDatas函数应该还有许多需要修改的地方,仅供参考。/**
     * 
     */
    package zhangshu.java.test;import java.util.ArrayList;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;/**
     * 
     * @author wdman
     * @version 1.0 2007-5-11
     */
    public class TestJava { /**
     * @param args
     */
    public static void main(String[] args) {
    //Test Data
    String data1 = "<html>\r\n" +
    "<div>内容1<br/><a>内容2</a></div>\r\n" +
    "<div><a>内容3</a><br/>内容4</div>\r\n" +
    "<div>内容5<br/><a>内容6</a></div>\r\n" +
    "</html>";
    String data2 = "<html>\r\n" +
    "<table><tr><td></td><td></td></tr><tr><td>内容1<td></tr></table>\r\n" +
    "<table><tr>内容2<td></td></tr></table>\r\n" +
    "<table><tr><td>内容3</td><td></td></tr><tr><td><td></tr></table>\r\n" +
    "</html>";

    String pattern1 = "<div><br/><a></a></div>";
    String pattern2 = "<table><tr><td></td><td></td></tr><tr><td><td></tr></table>";

    TestJava tj = new TestJava();

    String[] matchedString1 = tj.getTargetBlocks(data1,pattern1);
    System.out.println("匹配到的数据块:");
    for (int i=0; i<matchedString1.length; i++) {
    System.out.println(matchedString1[i]);
    }
    System.out.println("匹配到的数据:");
    for (int i=0; i<matchedString1.length; i++) {
    String[] values = tj.getTargetDatas(matchedString1[i],"<a></a>");
    for (int j=0; j<values.length; j++) {
    System.out.println(values[j]);
    }
    }
    String[] matchedString2 = tj.getTargetBlocks(data2,pattern2);
    System.out.println("匹配到的数据块:");
    for (int i=0; i<matchedString2.length; i++) {
    System.out.println(matchedString2[i]);
    }
    System.out.println("匹配到的数据:");
    for (int i=0; i<matchedString2.length; i++) {
    String[] values = tj.getTargetDatas(matchedString2[i],"<td></td>");
    for (int j=0; j<values.length; j++) {
    System.out.println(values[j]);
    }
    }
    }

    public String[] getTargetDatas(String data, String pattern) {
    ArrayList dataList = new ArrayList();
    String[] datas = getTargetBlocks(data,pattern);
    for (int i=0; i<datas.length; i++) {
    String[] newDatas = getTargetBlocks(datas[i],"><");
    for (int j=0; j<newDatas.length; j++) {
    String value = newDatas[j].substring(1, newDatas[j].length()-1);
    if (!value.equals("")) {
    dataList.add(value);
    }
    }
    }
    String[] values = new String[dataList.size()];
    for (int i=0; i<values.length; i++) {
    values[i] = (String)dataList.get(i);
    }
    return values;
    }


    public String[] getTargetBlocks(String datas, String pattern) {
    ArrayList matchedList = new ArrayList();
    pattern = this.getPattern(pattern);
    Pattern p = Pattern.compile(pattern);
    Matcher m = p.matcher(datas);

    while(m.find()){
    matchedList.add(m.group());
    }

    String[] returnStrs = new String[matchedList.size()];
    for (int i=0; i<matchedList.size(); i++) {
    returnStrs[i] = (String)matchedList.get(i);
    } return returnStrs;
    }

    private String getPattern(String pattern) {
    //pattern = pattern.replaceAll("\\", "\\\\");
    String[] parts = pattern.split(">");
    String returnData = "";
    for (int i=0; i<parts.length-1; i++) {
    returnData += parts[i] + ">[^<>]*";
    }

    if (parts[parts.length-1].length() == 1) {
    returnData += parts[parts.length-1];
    } else {
    returnData += parts[parts.length-1] + ">";
    }
    return returnData;
    }
    }