生物信息学中的XML标准如SBML如何映射到不同数据模型

来源:建站作者:深圳SEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《生物信息学中的XML标准如SBML如何映射到不同数据模型》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《生物信息学中的XML标准如SBML如何映射到不同数据模型》有用,将其分享出去将是对创作者最好的鼓励。

生物信息学领域的SBML(系统生物学标记语言)是基于XML的标准格式,主要用于描述生化反应、代谢通路、基因调控网络等生物系统模型,其结构化的XML设计让不同工具之间的数据交换更加便捷,但在实际分析中,经常需要将其映射到不同的数据模型以满足特定场景的使用需求。

生物信息学中的XML标准如SBML如何映射到不同数据模型

SBML的核心XML结构概述

SBML的XML文档有固定的层级结构,核心元素包含model根元素,下属listOfCompartments(区域列表)、listOfSpecies(物种列表)、listOfReactions(反应列表)等子模块,每个子模块下又包含对应的具体实例元素,比如species元素描述具体的生物分子,reaction元素描述生化反应过程。以下是一个简化的SBML XML片段示例:

<?xml version="1.0" encoding="UTF-8"?>
<sbml xmlns="http://www.sbml.org/sbml/level2/version4" level="2" version="4">
  <model id="simple_model" name="简单代谢模型">
    <listOfCompartments>
      <compartment id="cytosol" name="细胞质" size="1.0"/>
    </listOfCompartments>
    <listOfSpecies>
      <species id="glucose" name="葡萄糖" compartment="cytosol" initialAmount="10.0"/>
      <species id="atp" name="ATP" compartment="cytosol" initialAmount="5.0"/>
    </listOfSpecies>
    <listOfReactions>
      <reaction id="r1" name="葡萄糖磷酸化" reversible="false">
        <listOfReactants>
          <speciesReference species="glucose"/>
          <speciesReference species="atp"/>
        </listOfReactants>
        <listOfProducts>
          <speciesReference species="g6p"/>
          <speciesReference species="adp"/>
        </listOfProducts>
      </reaction>
    </listOfReactions>
  </model>
</sbml>

映射到关系型数据库模型

关系型数据库通过表结构存储数据,映射SBML时需要将XML的不同层级元素对应到不同的数据表,同时通过外键建立关联关系。常见的表设计如下:

表名核心字段对应SBML元素
compartmentid, name, size, model_idcompartment
speciesid, name, compartment_id, initial_amount, model_idspecies
reactionid, name, reversible, model_idreaction
reaction_reactantreaction_id, species_idspeciesReference(反应物)
reaction_productreaction_id, species_idspeciesReference(产物)

使用Python的xml.etree.ElementTree模块解析SBML并写入关系型数据库(以SQLite为例)的代码示例如下:

import xml.etree.ElementTree as ET
import sqlite3

# 解析SBML文件
tree = ET.parse("simple_model.xml")
root = tree.getroot()
# SBML的命名空间
ns = {"sbml": "http://www.sbml.org/sbml/level2/version4"}
model = root.find("sbml:model", ns)

# 连接SQLite数据库
conn = sqlite3.connect("sbml_data.db")
cursor = conn.cursor()

# 创建表结构
cursor.execute("""
CREATE TABLE IF NOT EXISTS compartment (
    id TEXT PRIMARY KEY,
    name TEXT,
    size REAL,
    model_id TEXT
)
""")
cursor.execute("""
CREATE TABLE IF NOT EXISTS species (
    id TEXT PRIMARY KEY,
    name TEXT,
    compartment_id TEXT,
    initial_amount REAL,
    model_id TEXT,
    FOREIGN KEY (compartment_id) REFERENCES compartment(id)
)
""")
cursor.execute("""
CREATE TABLE IF NOT EXISTS reaction (
    id TEXT PRIMARY KEY,
    name TEXT,
    reversible INTEGER,
    model_id TEXT
)
""")
cursor.execute("""
CREATE TABLE IF NOT EXISTS reaction_reactant (
    reaction_id TEXT,
    species_id TEXT,
    FOREIGN KEY (reaction_id) REFERENCES reaction(id),
    FOREIGN KEY (species_id) REFERENCES species(id)
)
""")

# 提取model_id
model_id = model.get("id")

# 插入区域数据
for comp in model.find("sbml:listOfCompartments", ns).findall("sbml:compartment", ns):
    comp_id = comp.get("id")
    comp_name = comp.get("name")
    comp_size = float(comp.get("size", 1.0))
    cursor.execute("INSERT OR REPLACE INTO compartment VALUES (?,?,?,?)",
                   (comp_id, comp_name, comp_size, model_id))

# 插入物种数据
for sp in model.find("sbml:listOfSpecies", ns).findall("sbml:species", ns):
    sp_id = sp.get("id")
    sp_name = sp.get("name")
    sp_comp = sp.get("compartment")
    sp_amount = float(sp.get("initialAmount", 0.0))
    cursor.execute("INSERT OR REPLACE INTO species VALUES (?,?,?,?,?)",
                   (sp_id, sp_name, sp_comp, sp_amount, model_id))

# 插入反应数据
for rxn in model.find("sbml:listOfReactions", ns).findall("sbml:reaction", ns):
    rxn_id = rxn.get("id")
    rxn_name = rxn.get("name")
    reversible = 1 if rxn.get("reversible") == "true" else 0
    cursor.execute("INSERT OR REPLACE INTO reaction VALUES (?,?,?,?)",
                   (rxn_id, rxn_name, reversible, model_id))
    # 插入反应物关联
    reactants = rxn.find("sbml:listOfReactants", ns)
    if reactants:
        for ref in reactants.findall("sbml:speciesReference", ns):
            sp_id = ref.get("species")
            cursor.execute("INSERT INTO reaction_reactant VALUES (?,?)", (rxn_id, sp_id))

conn.commit()
conn.close()

映射到面向对象模型

面向对象模型可以将SBML的元素直接映射为对应的类,更贴合SBML的层级结构,便于后续的业务逻辑处理。核心类设计如下:

  • Compartment类:属性包含id、name、size,对应SBML的compartment元素
  • Species类:属性包含id、name、compartment(关联Compartment对象)、initial_amount,对应SBML的species元素
  • Reaction类:属性包含id、name、reversible、reactants(关联Species列表)、products(关联Species列表),对应SBML的reaction元素
  • SBMLModel类:属性包含id、name、compartments、species、reactions,对应SBML的model元素

使用Python实现面向对象映射的代码如下:

import xml.etree.ElementTree as ET

class Compartment:
    def __init__(self, comp_id, name, size):
        self.id = comp_id
        self.name = name
        self.size = size

class Species:
    def __init__(self, sp_id, name, compartment, initial_amount):
        self.id = sp_id
        self.name = name
        self.compartment = compartment  # Compartment对象
        self.initial_amount = initial_amount

class Reaction:
    def __init__(self, rxn_id, name, reversible, reactants, products):
        self.id = rxn_id
        self.name = name
        self.reversible = reversible
        self.reactants = reactants  # Species对象列表
        self.products = products   # Species对象列表

class SBMLModel:
    def __init__(self, model_id, name):
        self.id = model_id
        self.name = name
        self.compartments = {}
        self.species = {}
        self.reactions = {}

    def add_compartment(self, comp):
        self.compartments[comp.id] = comp

    def add_species(self, sp):
        self.species[sp.id] = sp

    def add_reaction(self, rxn):
        self.reactions[rxn.id] = rxn

# 解析SBML并构建面向对象模型
def parse_sbml_to_oo(xml_path):
    tree = ET.parse(xml_path)
    root = tree.getroot()
    ns = {"sbml": "http://www.sbml.org/sbml/level2/version4"}
    model_elem = root.find("sbml:model", ns)
    model = SBMLModel(model_elem.get("id"), model_elem.get("name"))

    # 解析区域
    comps_elem = model_elem.find("sbml:listOfCompartments", ns)
    if comps_elem:
        for comp_elem in comps_elem.findall("sbml:compartment", ns):
            comp = Compartment(
                comp_elem.get("id"),
                comp_elem.get("name"),
                float(comp_elem.get("size", 1.0))
            )
            model.add_compartment(comp)

    # 解析物种
    species_elem = model_elem.find("sbml:listOfSpecies", ns)
    if species_elem:
        for sp_elem in species_elem.findall("sbml:species", ns):
            comp_id = sp_elem.get("compartment")
            comp = model.compartments.get(comp_id)
            sp = Species(
                sp_elem.get("id"),
                sp_elem.get("name"),
                comp,
                float(sp_elem.get("initialAmount", 0.0))
            )
            model.add_species(sp)

    # 解析反应
    rxns_elem = model_elem.find("sbml:listOfReactions", ns)
    if rxns_elem:
        for rxn_elem in rxns_elem.findall("sbml:reaction", ns):
            reversible = rxn_elem.get("reversible") == "true"
            # 解析反应物
            reactants = []
            reactants_elem = rxn_elem.find("sbml:listOfReactants", ns)
            if reactants_elem:
                for ref in reactants_elem.findall("sbml:speciesReference", ns):
                    sp_id = ref.get("species")
                    reactants.append(model.species.get(sp_id))
            # 解析产物
            products = []
            products_elem = rxn_elem.find("sbml:listOfProducts", ns)
            if products_elem:
                for ref in products_elem.findall("sbml:speciesReference", ns):
                    sp_id = ref.get("species")
                    products.append(model.species.get(sp_id))
            rxn = Reaction(
                rxn_elem.get("id"),
                rxn_elem.get("name"),
                reversible,
                reactants,
                products
            )
            model.add_reaction(rxn)
    return model

# 使用示例
sbml_model = parse_sbml_to_oo("simple_model.xml")
print(f"模型名称:{sbml_model.name},包含{len(sbml_model.reactions)}个反应")

映射到自定义JSON模型

JSON格式更轻量,适合网络传输和前端展示,映射时可以将SBML的层级结构直接转换为对应的JSON嵌套结构。转换后的JSON结构示例如下:

{
  "model_id": "simple_model",
  "model_name": "简单代谢模型",
  "compartments": [
    {
      "id": "cytosol",
      "name": "细胞质",
      "size": 1.0
    }
  ],
  "species": [
    {
      "id": "glucose",
      "name": "葡萄糖",
      "compartment_id": "cytosol",
      "initial_amount": 10.0
    },
    {
      "id": "atp",
      "name": "ATP",
      "compartment_id": "cytosol",
      "initial_amount": 5.0
    }
  ],
  "reactions": [
    {
      "id": "r1",
      "name": "葡萄糖磷酸化",
      "reversible": false,
      "reactants": ["glucose", "atp"],
      "products": ["g6p", "adp"]
    }
  ]
}

使用Python实现SBML到JSON映射的代码如下:

import xml.etree.ElementTree as ET
import json

def sbml_to_json(xml_path, json_path):
    tree = ET.parse(xml_path)
    root = tree.getroot()
    ns = {"sbml": "http://www.sbml.org/sbml/level2/version4"}
    model_elem = root.find("sbml:model", ns)
    result = {
        "model_id": model_elem.get("id"),
        "model_name": model_elem.get("name"),
        "compartments": [],
        "species": [],
        "reactions": []
    }

    # 处理区域
    comps_elem = model_elem.find("sbml:listOfCompartments", ns)
    if comps_elem:
        for comp_elem in comps_elem.findall("sbml:compartment", ns):
            result["compartments"].append({
                "id": comp_elem.get("id"),
                "name": comp_elem.get("name"),
                "size": float(comp_elem.get("size", 1.0))
            })

    # 处理物种
    species_elem = model_elem.find("sbml:listOfSpecies", ns)
    if species_elem:
        for sp_elem in species_elem.findall("sbml:species", ns):
            result["species"].append({
                "id": sp_elem.get("id"),
                "name": sp_elem.get("name"),
                "compartment_id": sp_elem.get("compartment"),
                "initial_amount": float(sp_elem.get("initialAmount", 0.0))
            })

    # 处理反应
    rxns_elem = model_elem.find("sbml:listOfReactions", ns)
    if rxns_elem:
        for rxn_elem in rxns_elem.findall("sbml:reaction", ns):
            rxn_data = {
                "id": rxn_elem.get("id"),
                "name": rxn_elem.get("name"),
                "reversible": rxn_elem.get("reversible") == "true",
                "reactants": [],
                "products": []
            }
            # 反应物
            reactants_elem = rxn_elem.find("sbml:listOfReactants", ns)
            if reactants_elem:
                for ref in reactants_elem.findall("sbml:speciesReference", ns):
                    rxn_data["reactants"].append(ref.get("species"))
            # 产物
            products_elem = rxn_elem.find("sbml:listOfProducts", ns)
            if products_elem:
                for ref in products_elem.findall("sbml:speciesReference", ns):
                    rxn_data["products"].append(ref.get("species"))
            result["reactions"].append(rxn_data)

    # 写入JSON文件
    with open(json_path, "w", encoding="utf-8") as f:
        json.dump(result, f, ensure_ascii=False, indent=2)

# 使用示例
sbml_to_json("simple_model.xml", "sbml_output.json")

映射注意事项

在实际映射过程中需要注意几个问题:一是SBML有多个版本,不同版本的XML元素和属性定义存在差异,解析时需要先确认SBML的版本和对应的命名空间;二是部分SBML元素包含可选属性,映射时需要做好默认值处理,避免数据缺失;三是如果SBML中包含数学公式等扩展内容,需要根据目标数据模型的特点做额外的适配处理,比如将MathML格式的公式转换为目标模型支持的表达式格式。

SBMLXML生物信息学数据模型映射修改时间:2026-07-08 05:06:21

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。