You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用SAX将圣经文本转为OSIS XML:如何优雅生成头部模板文本?

优雅生成OSIS XML头部的SAX方案

我太懂这种感觉了——用标准库SAX处理XML时,流式处理的爽感拉满,但碰到静态的大段头部模板,硬写字符串或者凑SAX方法总觉得别扭,完全破坏了代码的整洁度。刚好我之前处理类似的宗教文本XML生成时,摸索出几个优雅的方案,完全适配你的需求:

方案1:将静态头部封装在自定义ContentHandler中

既然用SAX,那就把头部的静态逻辑和业务处理逻辑封装在一起,继承xml.sax.saxutils.XMLGenerator,重写startDocumentendDocument方法,直接向输出流写入预定义的头部/尾部内容,代替SAX默认的生成逻辑。这样代码内聚,不用在业务逻辑里穿插模板字符串:

from xml.sax import saxutils

class OSISContentHandler(saxutils.XMLGenerator):
    def __init__(self, out, encoding='utf-8', osis_work_id='KJV'):
        super().__init__(out, encoding)
        self.out = out
        self.osis_work_id = osis_work_id

    def startDocument(self):
        # 写入自定义XML声明和OSIS根元素头部,支持动态参数
        header = f'''<?xml version="1.0" encoding="UTF-8"?>
<osis xmlns="http://www.bibletechnologies.net/2003/OSIS/namespace"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.bibletechnologies.net/2003/OSIS/namespace http://www.bibletechnologies.net/2003/OSIS/osisCore.2.1.xsd">
<osisText osisIDWork="{self.osis_work_id}" osisRefWork="{self.osis_work_id}">
'''
        self.out.write(header)

    def endDocument(self):
        # 写入尾部闭合标签
        footer = '''</osisText>
</osis>
'''
        self.out.write(footer)

# 使用示例
with open('bible.osis.xml', 'w', encoding='utf-8') as output_file:
    handler = OSISContentHandler(output_file, osis_work_id='NIV')
    # 这里开始处理圣经文本的流式生成
    handler.startElement('chapter', {'osisID': 'Gen.1'})
    handler.startElement('verse', {'osisID': 'Gen.1.1'})
    handler.characters('In the beginning God created the heaven and the earth.')
    handler.endElement('verse')
    handler.endElement('chapter')
    # 触发尾部生成
    handler.endDocument()

这个方案的好处是:所有XML生成逻辑都在Handler里,业务代码只需要专注于处理圣经文本的节点生成,头部的静态结构和动态参数(比如不同版本的osisIDWork)都能优雅处理。

方案2:分离模板文件,代码与配置解耦

如果头部模板比较复杂,或者需要频繁修改(比如调整schema版本、添加新的命名空间),把头部/尾部做成单独的模板文件会更方便,完全和Python代码分离,维护起来更轻松:

  1. 先创建两个模板文件:

    • osis_header.tpl
      <?xml version="1.0" encoding="UTF-8"?>
      <osis xmlns="http://www.bibletechnologies.net/2003/OSIS/namespace"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.bibletechnologies.net/2003/OSIS/namespace http://www.bibletechnologies.net/2003/OSIS/osisCore.2.1.xsd">
      <osisText osisIDWork="{osis_work_id}" osisRefWork="{osis_work_id}">
      
    • osis_footer.tpl
      </osisText>
      </osis>
      
  2. 然后在脚本中读取模板并写入输出流,再启动SAX的内容生成:

from xml.sax import saxutils

def generate_osis_bible(input_text, output_path, osis_work_id='KJV'):
    with open(output_path, 'w', encoding='utf-8') as output_file:
        # 写入动态格式化后的头部模板
        with open('osis_header.tpl', 'r', encoding='utf-8') as header_file:
            header_content = header_file.read().format(osis_work_id=osis_work_id)
            output_file.write(header_content)
        
        # 初始化SAX生成器,专注处理内容节点
        handler = saxutils.XMLGenerator(output_file, encoding='utf-8')
        # 这里省略处理input_text生成章节、经文节点的逻辑,示例如下:
        handler.startElement('chapter', {'osisID': 'Gen.1'})
        handler.startElement('verse', {'osisID': 'Gen.1.1'})
        handler.characters('In the beginning God created the heaven and the earth.')
        handler.endElement('verse')
        handler.endElement('chapter')
        
        # 写入尾部模板
        with open('osis_footer.tpl', 'r', encoding='utf-8') as footer_file:
            output_file.write(footer_file.read())

# 调用示例
generate_osis_bible('your_bible_text_source', 'output.osis.xml', osis_work_id='ESV')

这个方案的优势是:模板修改不需要动代码,非开发人员也能调整XML结构;如果需要支持多种OSIS配置,只需要准备不同的模板文件即可。

为什么这两个方案比硬写字符串优雅?

  • 完全贴合SAX的流式处理特性:直接向输出流写入静态内容,不会占用额外内存,和SAX的设计理念一致;
  • 代码职责清晰:业务逻辑专注于文本转节点,模板逻辑要么封装在Handler要么独立成文件,不会混在一起;
  • 支持动态参数:不管是封装在Handler还是用模板文件,都能轻松替换osisIDWork这类动态属性,不用拼接复杂字符串。

内容的提问来源于stack exchange,提问作者mcepl

火山引擎 最新活动