讲述如何快速调整思路,使用4suite 完成模板解析任务

-- Zoom.Quiet [2004-08-25 00:18:52]

1. 解决故事

1.1. 提出需求

040823 整理思路,发现从XSLT角度处理XML为数据源的模板解析,是最省心的方式!

  • 那未!问题变为:
    • 写出使用XSLT 语法解析Otter 目标代码的模板
    • 寻找Py 支持XSLT解析的模块

1.2. 逐一解决

最直接的方式来确定代码

1.2.1. XSLT写作

  • 当然是 XMLSpy!
  • 指定配置XML使用一个XSLT模板来解析自个儿:
  • 创建最简单的XSLT模板:
    <?xml version="1.0" encoding="UTF-8"?> 
    <!-- edited with XMLSPY v2004 rel. 3 U (http://www.xmlspy.com) by Zoom.Quiet (infopro.cn) -->
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:output method="xml" version="1.0" encoding="gb2312" indent="yes"/>
            <xsl:template match="/">
                    <xsl:for-each select="Otter">
                            <xsl:value-of select="@ProtocolName"/>
                    </xsl:for-each>
            </xsl:template>
    </xsl:stylesheet>
    
  • 直接在XMLSpy 中预览:
  • 成功!!!哈哈哈!easy! 再来根据XML的SDK 中XSLT 相关的语法,使用XSLT 逐步将目标代码解析出来,可以直接在XMLSpy 编辑界面中测试!感觉跟Python 脚本编辑一样!
  • 但是:

  • 解析结果中文,格式都看不到!看来还是要在实际执行环境中尝试!

1.2.2. 4Suite 使用

1.2.2.1. 初步尝试

  • 按照David 大大的文章:
  • 4XSLT 用法的样本 Python 代码片段

   1 from xml.xslt.Processor import Processor
   2 proc1,proc2 = Processor(),Processor()
   3 proc1.appendStylesheetUri('mime.xsl')
   4 result1 = processor.runUri('message.xml')
   5 proc2.appendStylesheetString(open('mime.xsl').read())
   6 result2 = proc2.runString(open('message.xml').read())
   7 print result1,result2
  • 呜乎哀哉!不能运行!
    >>> from xml.xslt.Processor import Processor 
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    ImportError: No module named xslt.Processor    
    
  • 可能升级了路径不同也!毕竟大大的文章是2002 年 1 月 的!
  • 直接探索路径!
    • CJKPython23\Lib\site-packages\Ft\Xml\Xslt\ 发现了包对应模块

1.2.2.2. 探寻代码

  • 嘿嘿嘿!列表中刚刚有人介绍说Python 哲学之一就是
    • 只要知道语法,就用不着文档!

      • 原文如何忘了,知者请补充是也乎!

  • >>> import Ft.Xml.Xslt 
    >>> dir(Ft.Xml.Xslt.Processor)
    ['BuiltInExtElements', 'DEFAULT_ENCODING', 'Domlette', 'EMPTY_NAMESPACE'
    , 'Error', 'Exslt', 'InputSource', 'MessageSource', 'Node'
    , 'OutputHandler', 'Processor', 'RtfWriter', 'STRING_TYPES'
    , 'StringWriter', 'StripElements', 'StylesheetReader', 'Uri'
    , 'Util', 'XSLT_IMT', 'XsltContext', 'XsltException', '__builtins__'
    , '__doc__', '__file__', '__name__', 'cStringIO', 'operator'
    , 'os', 'sys', 'types', 'warnings']
    >>> Ft.Xml.Xslt.Processor.__doc__
    '
    XSLT processing engine
    
    Copyright 2003 Fourthought, Inc. (USA).
    Detailed license and copyright information: http://4suite.org/COPYRIGHT
    Project home, documentation, distributions: http://4suite.org/
    
  • 咦咦咦??不得要领, 啊! 实际的是Ft.Xml.Xslt.Processor.Processor
  • >>> Ft.Xml.Xslt.Processor.Processor.__doc__ 
    "
        An XSLT processing engine (4XSLT).
    
        Typical usage:
    
        from Ft.Lib.Uri import OsPathToUri
        from Ft.Xml import InputSource
        from Ft.Xml.Xslt import Processor
        # this is just one of several ways to create InputSour
        styuri = OsPathToUri('/absolute/path/to/stylesheet.xsl
        srcuri = OsPathToUri('/absolute/path/to/doc.xml')
        STY = InputSource.DefaultFactory.fromUri(styuri)
        SRC = InputSource.DefaultFactory.fromUri(srcuri)
        proc = Processor.Processor()
        proc.appendStylesheet(STY)
        result = Processor.run(SRC)
    
        Optional constructor arguments are:
    
          stylesheetIncPaths: a list of alternate base URIs to
            when resolving relative hrefs in xsl:import/xsl:in
            instructions (useful when hiding included/imported
            stylesheets in private directories).
            Can also be supplied via the XSLTINCLUDE environme
            variable. These base URIs are only tried when the
            standard XSLT behavior of using the base URI of th
            xsl:import/include element fails to result in
            retrieval of a document.
    
          useEnvironment: a flag indicating whether the proces
            should use or ignore environment variables that af
            its configuration
    
          documentReader: an object that will be used to parse
            source documents (not stylesheets); defaults to
            Ft.Xml.Domlette.NonvalidatingReader. It can be any
            object that has a parse() method that returns a DO
            Domlette tree.
    
          implementation: the DOM implementation instance; nec
            if supplying a documentReader. Defaults to
            Ft.Xml.Domlette.implementation. Needs to have a
            createRootNode() method.
    
        See the run() method for additional options.
        "
    
  • 哈哈哈!完整的最新提示!
  • 仿照之进行代码组织!

1.2.2.3. 解决的关键代码

  • 反复尝试,发现,我需要的是从文件解析出结果,而不是从URL!
  • >>> dir(Ft.Xml.InputSource.DefaultFactory) 
    ['__doc__', '__init__', '__module__', '_klass'
    , 'fromStream', 'fromString', 'fromUri', 'resolver']
    
  • 哈哈哈!果然有 fromString!
  • 于是一切顺其自然:
       1 from Ft.Lib.Uri import OsPathToUri
       2 from Ft.Xml import InputSource
       3 from Ft.Xml.Xslt import Processor
       4 class Ft4xslt:
       5     """Otter模板解析类
       6         - 使用 4suite的XLST 解析引擎进行XSLT 的Otter 模板处理    """
       7     def __init__(self):
       8         """初始化环境        """
       9         self.processor = Processor.Processor()
      10     def parse(self,xmlfile,xsltfile):
      11         """模板主解析引擎        """
      12         STY = InputSource.DefaultFactory.fromString(xsltfile)
      13         SRC = InputSource.DefaultFactory.fromString(xmlfile)
      14         self.processor.appendStylesheet(STY)
      15         result = self.processor.run(SRC)
      16         return result
      17 if __name__ == '__main__':
      18     """模块自测    """
      19     xslt4 = Ft4xslt()
      20     ott = open("OtterTemplet\lib\messages\pcon-pmsg.xslt","r").read()
      21     otx = open("xml\uss.xml","r").read()
      22     print xslt4.parse(otx,ott)
    

1.3. 调试优化

  • 通过 ]python OtTxslt.py > tryOutport.py

  • 的方式,跟踪解析输出,逐步调整XSLT 模板,让生成的代码,与目标代码一致!
  • 最后,发现唯一的非期待输出就是头行的XML声明
  • 简单的在 Ft4xlst.parse 输出中加上过滤:
    • return result.replace("<?xml version=\"1.0\" encoding=\"gb2312\"?>","")

  • KO!完美解决!

  • 至此不过 2小时左右的尝试!

2. 总结

  • 思路最重要!

    • 明确的思路可以指引最小的路径达到目的!
  • 寻找巨人的肩膀!

    • 相似的问题,确定有人已经问过!解决过了!!
    • 我们最好的编程途径,就是寻找最成熟的代码,然后修改为我用!

3. 问题

  •     E:\LAMPS\CJKPython23\lib\site-packages\Ft\Xml\InputSource.py:203: RuntimeWarning: Creation of InputS
    ource without a URI
      return apply(self.fromStream, (stream, uri) + v_args, kw_args)
    
  • 虽然工作正常,可是总是报错!??!?!? ;)