DOCX math: a delimiter with several arguments keeps only the last one

Abierto Apto para principiantes
#2,573 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@drakeo338 ya está trabajando en esto.

Desde el 1/10/2026.

  • #2574 de @drakeo338 — abierto
  • #2636 de @iosayin — cerrado sin fusionar
  • #2654 de @iosayin — abierto
  • #2665 de @dajiaohuang — abierto
  • #2757 de @OUAO-FRANK — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
86/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
python
Área
tooling

Línea de trabajo

Comienza en packages/markitdown/src/markitdown/converter_utils/docx/math/omml.py, leyendo oMath2Latex.do_d, Pr, process_children_dict() y process_children_list(). Vuelve a ejecutar los ejemplos XML del issue y verifica después que todos los argumentos delimiter se conserven en orden y que los casos de sepChr explícito, omitido y sin valor produzcan los separadores esperados.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

When a Word equation contains a delimiter (<m:d>) with more than one argument, MarkItDown keeps only the last argument and drops the rest without any warning. The separator character (<m:sepChr>) is never read either.

Word writes this structure for the bracket templates "with separators" (Insert > Equation > Bracket), for example (a|b), {x|x>0} and bra-ket notation.

Repro

from xml.etree import ElementTree as ET
from markitdown.converter_utils.docx.math.omml import OMML_NS, oMath2Latex

M = f'xmlns:m="{OMML_NS[1:-1]}"'

def latex(xml):
    return oMath2Latex(ET.fromstring(f"<m:oMath {M}>{xml}</m:oMath>")).latex

r = lambda t: f"<m:r><m:t>{t}</m:t></m:r>"

# Explicit separator
print(latex(r("f") + '<m:d><m:dPr><m:sepChr m:val=","/></m:dPr>'
            f"<m:e>{r('x')}</m:e><m:e>{r('y')}</m:e></m:d>"))
# -> f\left(y\right)

# Set-builder braces, default separator (no sepChr)
print(latex('<m:d><m:dPr><m:begChr m:val="{"/><m:endChr m:val="}"/></m:dPr>'
            f"<m:e>{r('x')}</m:e><m:e>{r('x>0')}</m:e></m:d>"))
# -> \left\{x>0\right\}

End to end, adding the first equation to a copy of tests/test_files/equations.docx makes MarkItDown().convert() emit $$f\left(y\right)$$.

Expected vs actual

Input Expected Actual
f + <m:d> with sepChr=",", args x, y f\left(x,y\right) f\left(y\right)
<m:d> braces, no sepChr, args x, x>0 \left\{x|x>0\right\} \left\{x>0\right\}
<m:d> with sepChr=";", args a, b, c \left(a;b;c\right) \left(c\right)

In the OMML schema (ECMA-376 / ISO/IEC 29500-1, CT_D), <m:e> has maxOccurs="unbounded". The sepChr element "specifies the character that separates base arguments e in the delimiter object d". When the element is omitted, the separator is a vertical bar (U+2502). When it is present without m:val, there is no separator. See the Open XML SDK SeparatorChar reference, which reproduces the spec text. Dropping arguments silently loses document content.

Cause

In packages/markitdown/src/markitdown/converter_utils/docx/math/omml.py, oMath2Latex.do_d reads its children with process_children_dict(). That function returns a dict keyed by tag name, so each <m:e> overwrites the previous one and c_dict["e"] holds only the last argument. Separately, Pr.__val_tags (and Pr.tag2meth) do not include sepChr, so pr.sepChr is always None.

Suggested fix

In do_d, collect every <m:e> in order with process_children_list(elm, include=("e",)). Have Pr read sepChr, with an empty value when m:val is missing. Then join the arguments with the separator, falling back to | when sepChr is absent. A single-argument delimiter gives the same output as before.

Environment

  • markitdown main at 1f9530a (0.1.8)
  • Python 3.13, macOS

AI assistance: drafted with an AI coding assistant (Claude). The reproduction above was run locally against the current default branch.

Lenguaje dominante
Python
Estrellas
194k
Forks
14.5k
Merge medio
1 h 43 min
PR fusionados (30 d)
8

Preparar el entorno

Abrir en Codespaces

Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.

  • Incluye un Dockerfile o un archivo de Docker Compose
  • Sin plantilla de pull request
  • Sin guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de microsoft/markitdown

Todos los issues de microsoft/markitdown

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.