2017-10-09 3 views
0

Ich konvertiere Text mit Latex-Stil-Gleichung in MS-Word-Dokument mit Apache POI. Mit etwas Hilfe konnte ich es erfolgreich implementieren, aber wenn die Linie mehr als eine Gleichung hat, dann erzeugt es ein falsches Ergebnis.Wie fügen Sie mehrere Gleichungen inline mit Text in Apache POI Word?

folgende ist mein Code:

import java.io.*; 
import org.apache.poi.xwpf.usermodel.*; 

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; 
import org.openxmlformats.schemas.officeDocument.x2006.math.CTOMath; 
import org.openxmlformats.schemas.officeDocument.x2006.math.CTOMathPara; 

import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.transform.stream.StreamResult; 

import uk.ac.ed.ph.snuggletex.SnuggleInput; 
import uk.ac.ed.ph.snuggletex.SnuggleEngine; 
import uk.ac.ed.ph.snuggletex.SnuggleSession; 

import java.io.IOException; 

public class CreateWordFormulaFromMathML { 

static File stylesheet = new File("MML2OMML.XSL"); 
static TransformerFactory tFactory = TransformerFactory.newInstance(); 
static StreamSource stylesource = new StreamSource(stylesheet); 

static CTOMath getOMML(String mathML) throws Exception { 
    Transformer transformer = tFactory.newTransformer(stylesource); 

    StringReader stringreader = new StringReader(mathML); 
    StreamSource source = new StreamSource(stringreader); 

    StringWriter stringwriter = new StringWriter(); 
    StreamResult result = new StreamResult(stringwriter); 
    transformer.transform(source, result); 

    String ooML = stringwriter.toString(); 
    stringwriter.close(); 

    CTOMath ctOMath = CTOMath.Factory.parse(ooML); 
    return ctOMath.getOMathArray(0); 
} 

public static void main(String[] args) throws Exception { 

    XWPFDocument document = new XWPFDocument(); 

    String mstr = "The expression is as: $ax^2 + bx = c$ is easier to understand than $$ax^2 + \\frac{\\sin^{-1}\\theta}{\\cot{-1}} \\times y_1$$ or anything in \\[ ay^2 + b_2 \\theta\\]"; 

    XWPFParagraph paragraph = document.createParagraph(); 
    XWPFRun run = paragraph.createRun(); 
// run.setText(""); 

    SnuggleEngine engine = new SnuggleEngine(); 
    SnuggleSession session = engine.createSession(); 

    SnuggleInput input = new SnuggleInput(mstr); 
    session.parseInput(input); 

    String mathML = session.buildXMLString(); 
    System.out.println("Input " + input.getString() + " was converted to:\n" + mathML + "\n\n"); 


for(String s : mathML.split("\\s+(?=<math)|(?<=</math>)\\s+")){ 

if (s.startsWith("<math")) 
{ 
    CTOMath ctOMath = getOMML(s); 
    System.out.println(s); 

    CTP ctp = paragraph.getCTP(); 
    ctp.setOMathArray(new CTOMath[]{ctOMath});   
} 
else 
{ 
    run.setText(s + " "); 
    System.out.println(s); 
} 
} 

    document.write(new FileOutputStream("CreateWordFormulaFromMathML.docx")); 
    document.close(); 

} 
} 

Diese produzieren ein Dokument mit

Der Ausdruck ist als: leichter zu verstehen ist als oder irgendetwas in ay^2 + b_2 \ theta

Hinweis : (ay^2 + b_2 \ theta) ist korrekt im Format der Wortgleichung.

Was ich brauche, ist Inline-Text mit mehrfachen Gleichungen in der Mitte.

Antwort

1

Wie an Lösungsaufgaben zum Erstellen von Office OpenXML Dateien wie *.docx?

Office OpenXML Dateien wie *.docx sind nur ZIP Archive. Wir können sie entpacken und in die Interna schauen. In *.docx finden wir /word/document.xml und dort finden wir XML, die die Dokumentstruktur beschreibt. Für die Absätze Formel inline mit finden wir so etwas wie:

<w:p> 
<w:r> 
    <w:t>text</w:t> 
</w:r> 
<m:oMath>... </m:oMath> 
<w:r> 
    <w:t>text</w:t> 
</w:r> 
<m:oMath>... </m:oMath> 
... 
</w:p> 

Also brauchen wir mehrere Läufe den Text halten und zwischen ihnen mehr .

Deshalb hat der Absatz eine OMathArrayCTOMath[]. Und Ihr Code überschreibt dieses Array mit einem neuen Array mit einenCTOMathjeder Zeit eine zusätzliche CTOMath gefunden wurde. Stattdessen muss eine zusätzliche CTOMath zum Array hinzugefügt werden, jedes Mal, wenn ein zusätzlicher CTOMath gefunden wurde.

Um zu wissen, was wir mit org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP Absätze tun können, benötigen wir eine Dokumentation dafür. Am besten habe ich gefunden grepcode.com. Dort finden wir CTP.addNewOMath() und CTP.setOMathArray(int, CTOMath).

Ändern So Ihr Code wie:

for(String s : mathML.split("\\s+(?=<math)|(?<=</math>)\\s+")){ 

    if (s.startsWith("<math")) { 
    CTOMath ctOMath = getOMML(s); 
    System.out.println(s); 

    CTP ctp = paragraph.getCTP(); 
    ctp.addNewOMath(); 
    ctp.setOMathArray(ctp.sizeOfOMathArray()-1, ctOMath);   
    } 
    else { 
    run = paragraph.createRun(); 
    run.setText(s + " "); 
    System.out.println(s); 
    } 
    } 

funktionieren sollte.

+0

Es funktioniert einwandfrei! Danke! –

Verwandte Themen