以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 WORD to XML, HTML to XML 』  (http://bbs.xml.org.cn/list.asp?boardid=13)
----  [跪求赐教]关于JTidy中XSLT文件的问题  (http://bbs.xml.org.cn/dispbbs.asp?boardid=13&rootid=&id=62832)


--  作者:asmdy
--  发布时间:5/19/2008 3:44:00 PM

--  [跪求赐教]关于JTidy中XSLT文件的问题
毕业设计要用到JTidy将HTML文件转换成XML文件,期间遇到了一些问题,希望高手能够帮帮忙解决啊!谢谢!

    在网上搜索了关于使用JTidy来将HTML网页转换成XML DOM对象的介绍,大多数提供的JTidy代码如下所示:

package myTidy;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.tidy.Configuration;
import org.w3c.tidy.Tidy;
import org.xml.sax.SAXException;

public class HTMLParserByW3CDOM {
 private Templates template;
 
// public HTMLParserByW3CDOM(){
//  
// }
/*
  * 解析网页
  * XSLTFileName 用于解析网页的样式表文件名
  * HTMLFileName 待解析的网页文件名
  * OutputFileName 输出文件名
  */
 public void parser(String HTMLFileName, String OutputFileName)
 {
  if( this.template != null){
   Document doc =  this.HTMLToXML( HTMLFileName ); // 解析网页,返回 W3c Document 文档对象
   Transformer(doc, OutputFileName);    // 使用样式表转换 Document 为最终结果
  }
 }

/**
  * 解析网页,转换为 W3C Document 文档对象
  * @param fileName HTML 网页的文件名
  * @return   utf-8 W3C Document 文档对象
  */
 private Document HTMLToXML(String fileName) {
  Logger log = Logger.getLogger("HTMLToXML");
  Document doc = null;
  try{
   FileInputStream in = new FileInputStream( fileName ); // 打开文件,转换为 UTF-8 编码  
   InputStreamReader isr = new InputStreamReader(in, "GB2312"); // 源文件编码为 gb2312
   
   File tmpNewFile = File.createTempFile("GB2312",".html"); // 转换后的文件,设定编码为 utf-8
   FileOutputStream out = new FileOutputStream( tmpNewFile ); // 需要将文件转换为字符流
   OutputStreamWriter osw = new OutputStreamWriter( out , "UTF-8");// 指定目标编码为 utf-8
   osw.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
   
   char[] buffer = new char[10240];      // 文件缓冲区
   int len = 0;           // 使用字符读取方式,循环读取源文件内容
   while( (len = isr.read(buffer)) !=-1 )     // 转换后写入目标文件中
   {
    osw.write( buffer, 0, len);
   }
   osw.close();           // 转换完成
   isr.close();
   out.close();
   in.close();
   
   if( log.isLoggable( Level.INFO)){
    log.info("HTML 文档转 UTF-8 编码完成!");
   }
   
   //  设置 tidy ,准备转换
   Tidy tidy = new Tidy();
   tidy.setXmlOut(true);    // 输出格式 xml
   tidy.setDropFontTags(true);   // 删除字体节点
   tidy.setDropEmptyParas(true);  // 删除空段落
   tidy.setFixComments(true);   // 修复注释
   tidy.setFixBackslash(true);   // 修复反斜杆
   tidy.setMakeClean(true);   // 删除混乱的表示
   tidy.setQuoteNbsp(false);   // 将空格输出为   
   tidy.setQuoteMarks(false);   // 将双引号输出为 "
   tidy.setQuoteAmpersand(true);  // 将 & 输出为 &
   tidy.setShowWarnings(false);  // 不显示警告信息
   tidy.setCharEncoding(Configuration.UTF8); // 文件编码为 UTF8
   
   
   FileInputStream src = new FileInputStream( tmpNewFile ); //
   doc = tidy.parseDOM( src ,null ); // 通过 JTidy 将 HTML 网页解析为
   src.close();           // W3C 的 Document 对象
   tmpNewFile.delete();         // 删除临时文件
   
   NodeList list = doc.getChildNodes();     // 页面中 DOCTYPE 中可能问题
   for(int i=0; i<list.getLength(); i++)     // 删除 DOCTYPE 元素
   {
    Node node = list.item(i);
    if( node.getNodeType() == Node.DOCUMENT_TYPE_NODE) // 查找类型定义节点
    {
     node.getParentNode().removeChild( node );

     if( log.isLoggable( Level.INFO)){
      log.info("已经将文档定义节点删除!" );
     }
    }
   }
   
   list = doc.getElementsByTagName("script");    // 脚本中的注释有时有问题
   for(int i=0; i<list.getLength(); i++){     // 清理 script 元素
    Element script = (Element) list.item(i);
    if( script.getFirstChild() != null){
     if( log.isLoggable( Level.FINEST)){
      log.finest("删除脚本元素: " + script.getFirstChild().getNodeValue());
     }
     script.removeChild( script.getFirstChild());
    }
   }
   
   list = doc.getElementsByTagName("span");    // sina 中 span 元素有时有问题
   for(int i=0; i<list.getLength(); i++){     // 清理 span 元素
    Element span = (Element) list.item(i);
    span.getParentNode().removeChild( span );
    if( log.isLoggable( Level.FINEST)){
     log.finest("删除 span 元素: " );
    }
   }
   

//   list = doc.getElementsByTagName("sohuadcode");   // 清除 sohuadcode 元素
//   for(int i=0; i<list.getLength(); i++){
//    Element sohuadcode = (Element) list.item(i);
//    sohuadcode.getParentNode().removeChild( sohuadcode );
//   }
   
   if( log.isLoggable( Level.INFO)){
    log.info("HTML 文档解析 DOM 完成.");
   }
   }catch(Exception e){
    log.severe(e.getMessage());
    e.printStackTrace();
    }finally
    {
   
    }
    return doc;
 }

/**
  * 解析转换的样式表,保存为模板
  * @param xsltFileName  样式表文件名
  * @return     样式表模板对象
  */
 public Templates setXSLT(String xsltFileName)
 {
  Logger log = Logger.getLogger( "setXSLT" );
  File xsltFile = new File( xsltFileName );
  StreamSource xsltSource = new StreamSource( xsltFile );  // 使用 JAXP 标准方法建立样式表的模板对象
  TransformerFactory tff = TransformerFactory.newInstance(); // 可以重复利用这个模板
  Templates template = null;
  try {
   template = tff.newTemplates( xsltSource );
   if( log.isLoggable( Level.INFO)){
    log.info("样式表文件 " + xsltFileName + " 解析完成");
   }
   } catch (TransformerConfigurationException e) {
    log.severe( e.getMessage() );
   }
   
   this.template = template;
   return template;
 }

/**
  * 使用样式表转换文档对象,得到最终的结果
  * @param doc   文档对象
  * @param outFileName 保存转换结果的文件名
  */
 private void Transformer(Document doc , String outFileName )
 {
  Logger log = Logger.getLogger( "Transformer" );
  try {
   Source source = new DOMSource( doc );
   
   File outFile = new File( outFileName );
   Result result = new StreamResult( outFile );
   
   Transformer transformer = template.newTransformer(); // 使用保存的样式表模板对象
   transformer.transform(source, result );     // 生成转换器,转换文档对象
   if( log.isLoggable( Level.INFO)){
    log.info("转换完成, 请查看 " + outFileName + " 文件。");
   }
   } catch (Exception e) {
    log.severe( e.getMessage() );
   }
 }
 
 public static void main(String args[]){
  HTMLParserByW3CDOM hpbwd = new HTMLParserByW3CDOM();
  hpbwd.template = hpbwd.setXSLT(args[0]);
  hpbwd.parser(args[1], args[2]);
  
 }
}

    其运行时需要给定一个HTML网页的地址、样式表文件名、以及所要输出的XML的文件名。
    我在Eclipse3.2 下运行此代码,并给出了运行参数tidy051604.xsl file:///D:/joyo_software/1.htm tidy051604.xml,其中,file:///D:/joyo_software/1.htm是我本地的一个HTML文件,tidy051604.xml是我要输出的XML文件。
    现在问题出在tidy051604.xsl上,当我试着编译运行的时候,便出现错误提示“F:\workspace\tidyTest\tidy051604.xsl (系统找不到指定的文件。)   无法找到样式表”,以及提示“myTidy.HTMLParserByW3CDOM setXSLT严重: 无法编译样式表”。那么,根据这个提示,是不是要我自己根据具体的HTML网页编写对应的XSL文件呢?如果遇到很复杂的HTML文件,这种工作量岂不很大?就算网页不复杂,那我要编写的是.xsl文件还是.xslt文件?
    谢谢大家!


--  作者:fangel2000
--  发布时间:6/18/2008 3:06:00 PM

--  
你是将HTML转换成XML还是XHTML?
一般的JTidy转换成的是XHTML,它已经基于XML语法了,但是标签还是基于HTML的
如果转换成XHTML的话就不需要设计样式表文件了
如果转换成XML的话,那就先转换成XHTML,然后针对这个XHTML用XSLT转换成结构良好的XML文件
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
46.875ms