我写了个组件用来从XML文件中读取其中某些节点的值,然后用数据库中的相应的数据来替换其中部分节点值,用更改后的文件创建一个新的XML文件,在不通过Tomcat和Sevlet的时候能正常工作,但在Tomcat中通过Servlet来调用这个组件时就报这个错误:
The output format must have a '{http://xml.apache.org/xalan}content-handler' property!传入的参数都是新文件名(带地址,如:D:\result.xml)
请各路高手帮忙解决,非常感谢!

解决方案 »

  1.   

    一:Servlet类:package com.hnedw.report;import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.naming.*;
    import java.util.*;
    import java.io.*;/**
     * <p>File Name  : ReportServiceServlet.java </p>
     * <p>Description: 报表应用Web控制器类 </p>
     * <p>Create Date: 2005-12-12 </p>
     * <p>Modify Date: 2005-12-12 </p>
     * <p>Company    : </p>
     * @author ylpeng
     * @version 1.0
     */
    public class ReportServiceServlet extends HttpServlet
    {
    /**
         * Function:服务方法,截取报表应用中所有Web请求,根据事件类型进行相应转发处理
         * @param request HttpServletRequest   Web请求对象
         * @param response HttpServletResponse Web响应对象
         */
    public void service(HttpServletRequest request,HttpServletResponse response){
    response.setContentType("text/html");
    RequestDispatcher dispatcher = null;
    try{
    response.setCharacterEncoding("GBK");
    request.setCharacterEncoding("GBK");
    String event = request.getParameter("event").trim();

    //初始化报表列表
    if(event.equals("load")){
    loadReportList(request,response);
    dispatcher = request.getRequestDispatcher("/report/index.jsp");
    }
    //创建请求的报表
    else if(event.equals("build")){
    buildReport(request,response);
    dispatcher = request.getRequestDispatcher("/report/index.jsp");
    }
    else
    throw new Exception("请求事件错误");

    dispatcher.forward(request,response);
    }
    catch(Exception e){
    try{
    PrintWriter writer = response.getWriter();
    writer.println(e.getMessage());
    }
    catch(IOException ioe){
    ioe.printStackTrace();
    }
    }
    }

    /**
         * Function:从数据库中获取当前用户能查看的报表集合并存入page_bean
         * @param request HttpServletRequest   Web请求对象
         * @param response HttpServletResponse Web响应对象
         */
    private void loadReportList(HttpServletRequest request,HttpServletResponse response)
    throws Exception
    {
    ReportDAO dao = new ReportDAO();
    ReportPageBean pageBean = new ReportPageBean();
    String sqlStr = "select report_id,report_name from trm_report";
    ArrayList[] reports = dao.getReportList(sqlStr);
    pageBean.setReports(reports);
    pageBean.setReportCount(((ArrayList)reports[0]).size());
    HttpSession session = request.getSession(true);
    session.setAttribute("page_bean",pageBean);
    }

    /**
         * Function:根据用户请求的资源创建报表
         * @param request HttpServletRequest   Web请求对象
         * @param response HttpServletResponse Web响应对象
         */
    private void buildReport(HttpServletRequest request,HttpServletResponse response)
    throws Exception
    {
    ReportDAO dao = new ReportDAO();
    XMLReport report = new XMLReport();
    String area = request.getParameter("area").trim();
    String startDate = request.getParameter("startDate").trim();
    String endDate = request.getParameter("endDate").trim();
    String reportID = request.getParameter("reportID").trim();

    String template = dao.getTemplateFile(reportID);
    template = getServletConfig().getServletContext().getRealPath(template);
    String target = template.substring(0,template.lastIndexOf(".")) + "-result.xml";
    report.runReport(template,target,area,startDate,endDate);//调用生成报表工具类,出错的就是这句

    //设置模型Bean中的报表文件属性
    HttpSession session = request.getSession(true);
    ReportPageBean pageBean = (ReportPageBean)session.getAttribute("page_bean");
    pageBean.setCurrentReport(target);
    }
    }
      

  2.   

    二:报表类:package com.hnedw.report;import java.io.*;
    import java.util.*;
    import javax.xml.parsers.*;
    import javax.xml.transform.*;
    import javax.xml.transform.dom.*;
    import javax.xml.transform.sax.*;
    import javax.xml.transform.stream.*;
    import org.xml.sax.*;
    import org.w3c.dom.*;/**
     * <p>File Name  : XMLReport.java </p>
     * <p>Description: 基于XML的报表应用API,用数据库中的相应值替换报表模板中标准编码值 </p>
     * <p>Create Date: 2005-12-08 </p>
     * <p>Modify Date: 2005-12-12 </p>
     * <p>Company    : </p>
     * @author ylpeng
     * @version 1.0
     */
    public class XMLReport
    {
    private DocumentBuilderFactory factory;
    private DocumentBuilder builder;

    /**
         * Function:构造函数,初始化主要的通用的XML API
         */
    public XMLReport(){
    try{
    factory = DocumentBuilderFactory.newInstance();
          factory.setValidating(false);
         builder = factory.newDocumentBuilder();
         builder.setErrorHandler(new MyErrorHandler());
    }
    catch(ParserConfigurationException parserException){
             parserException.printStackTrace();
        }
    }

    /**
         * Function:得到模板文件中的所有标准编码节点的编码集合,并存入内存变量中
         * @return ArrayList
         * @param fileName String 模板文件名
         */
    public ArrayList getStandardCodeList(String fileName){
    ArrayList codeList = new ArrayList();
    Document document;
         try {
         document = builder.parse(new File(fileName.trim()));
    Node root = document.getDocumentElement();
    if(root.getNodeType() == Node.ELEMENT_NODE){
    Element rootElement = (Element)root;
    NodeList dataNodeList = rootElement.getElementsByTagName("Data");

    for(int i = 0;i < dataNodeList.getLength();i++){
    Node code = dataNodeList.item(i);
    Text codeValue = (Text)code.getChildNodes().item(0);
    String codeText = codeValue.getData().trim();
    if(codeText.startsWith("$$",0)){
    codeList.add(codeText);
    }
    }
    }
            } 
            catch(IOException ioException){
                ioException.printStackTrace();
                System.exit(1);
            }
            catch(SAXException saxException){
                saxException.printStackTrace();         
            }
            return codeList;      
        }
        
        /**
         * Function:根据报表模板和指标值在数据库中的映射集合创建报表文件
         * @param sourceFile String 模板文件名
         * @param targetFile String 最后生成的报表文件名
         * @param codeMapping HashMap 模板中的指标集合和对应的指标值的集合构成的Map对象
         */
        public void buildNewFile(String sourceFile,String targetFile,HashMap codeMapping){
    Document document;
         try{
         document = builder.parse(new File(sourceFile.trim()));
    Node root = document.getDocumentElement();
    if(root.getNodeType() == Node.ELEMENT_NODE){
    Element rootElement = (Element)root;
    NodeList dataNodeList = rootElement.getElementsByTagName("Data");
    for(int i = 0;i < dataNodeList.getLength();i++){
    Node code = dataNodeList.item(i);
    Text codeValue = (Text)code.getChildNodes().item(0);
    String codeText = codeValue.getData().trim();
    if(codeText.startsWith("$$",0)){
    if(codeMapping.containsKey(codeText)){
    Text mappingValue = document.createTextNode(
    codeMapping.get(codeText).toString());
    code.replaceChild(mappingValue,codeValue);
    }
    else codeValue.setData("");
    }
    }
    }
    Source xmlSource = new DOMSource(document);
    Result result = new StreamResult(new FileOutputStream(targetFile.trim()));
    //StreamResult result = new StreamResult(new File(targetFile.trim()));
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
                transformer.setOutputProperty(OutputKeys.INDENT,"yes");
         transformer.setOutputProperty(OutputKeys.STANDALONE,"yes");
              transformer.transform(xmlSource, result);
            } 
            catch(IOException ioException){
                ioException.printStackTrace();
                System.exit(1);
            }
            catch (SAXException saxException){
                saxException.printStackTrace();         
            }
            catch(TransformerException transformerError){
                System.err.println("Error transforming document");
                transformerError.printStackTrace();
            }     
        }
        
        /**
         * Function:根据报表所需参数运行报表
         * @param sourceFile String 模板文件名
         * @param targetFile String 最后生成的报表文件名
         * @param areaCode String 本地网编码
         * @param startDate String 开始时间
         * @param endDate String   结束时间
         */
        public void runReport(String sourceFile,String targetFile,String areaCode,String startDate,String endDate){
         ArrayList codeList = this.getStandardCodeList(sourceFile);
         String sqlString = " select '$$'||trim(area_id)||'-'||trim(measure_item_id),sum(measure_value) " +  
    " from pd_martdata.bas_measure_value where Time_Cd BETWEEN '" + startDate.trim() + "' AND '" + 
    endDate.trim() + "' AND '$$'||trim(area_id)||'-'||trim(measure_item_id) in ";
         String str = "";
            for(int i = 0;i < codeList.size();i++){
             str += "'" + codeList.get(i).toString().trim() + "',";
            }
            str = str.substring(0,str.length() - 1);
            str = sqlString + "(" + str + ")";
            if(!areaCode.equals("all"))
             str += " AND trim(area_id) LIKE '" + areaCode.trim() + "%' ";
            str += " group by 1 order by 1;";
            
            //得到标准编码的映射集合
         HashMap codeMapping = ReportDAO.getCodeMapping(str);
         this.buildNewFile(sourceFile,targetFile,codeMapping);
        }

    /**
         * Function:程序入口,测试用
         */
    public static void main(String[] args){
    XMLReport report = new XMLReport();
    report.runReport("D:\\report.xls","D:\\result.xls","all","20040101","20051231");
    }
    }
      

  3.   

    http://docs.sun.com/source/819-1068/tshooting.html