- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 Apache POI 创建自动 (.docx) MS Word 文件。 Java程序的输入包含文本、图像和LaTeX风格的方程(嵌入$$或[])。
我的问题是如何在 Word 中添加这个 LaTeX 样式方程,以便当在 MS Word 中编辑 .docx 文件时,它会将方程识别为 MS Word 样式方程(OMML 类型)
注意:我认为应该将 LaTeX 方程转换为 MathML。如果是这样,那么如何将 MathML 添加到 .docx 中?
最佳答案
Microsoft 提供了 XSLT 样式表,用于将 OMML 转换为 MathML (OMML2MML.XSL
) 以及使用 XSLT 将 MathML 转换为 OMML (
.MML2OMML.XSL
)
如果您已安装 Microsoft Office
,您将在 Office 程序目录中找到这些文件。在我的系统中:
使用它,我们可以使用 XSLT 将 MathML 转换为 OMML。
示例:
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 org.openxmlformats.schemas.officeDocument.x2006.math.CTR;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.xmlbeans.XmlCursor;
/*
needs the full ooxml-schemas-*.jar or poi-ooxml-full-5.0.0.jar as mentioned in https://poi.apache.org/faq.html#faq-N10025
*/
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();
CTOMathPara ctOMathPara = CTOMathPara.Factory.parse(ooML);
CTOMath ctOMath = ctOMathPara.getOMathArray(0);
//for making this to work with Office 2007 Word also, special font settings are necessary
XmlCursor xmlcursor = ctOMath.newCursor();
while (xmlcursor.hasNextToken()) {
XmlCursor.TokenType tokentype = xmlcursor.toNextToken();
if (tokentype.isStart()) {
if (xmlcursor.getObject() instanceof CTR) {
CTR cTR = (CTR)xmlcursor.getObject();
cTR.addNewRPr2().addNewRFonts().setAscii("Cambria Math");
cTR.getRPr2().getRFonts().setHAnsi("Cambria Math"); // up to apache poi 4.1.2
//cTR.getRPr2().getRFontsArray(0).setHAnsi("Cambria Math"); // since apache poi 5.0.0
}
}
}
return ctOMath;
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("The Pythagorean theorem: ");
String mathML =
"<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
+"<mrow>"
+"<msup><mi>a</mi><mn>2</mn></msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup><mo>=</mo><msup><mi>c</mi><mn>2</mn></msup>"
+"</mrow>"
+"</math>";
CTOMath ctOMath = getOMML(mathML);
System.out.println(ctOMath);
CTP ctp = paragraph.getCTP();
ctp.setOMathArray(new CTOMath[]{ctOMath});
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("The Quadratic Formula: ");
mathML =
"<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
+"<mrow>"
+"<mi>x</mi><mo>=</mo><mfrac><mrow><mrow><mo>-</mo><mi>b</mi></mrow><mo>±</mo><msqrt><mrow><msup><mi>b</mi><mn>2</mn></msup><mo>-</mo><mrow><mn>4</mn><mo></mo><mi>a</mi><mo></mo><mi>c</mi></mrow></mrow></msqrt></mrow><mrow><mn>2</mn><mo></mo><mi>a</mi></mrow></mfrac>"
+"</mrow>"
+"</math>";
ctOMath = getOMML(mathML);
System.out.println(ctOMath);
ctp = paragraph.getCTP();
ctp.setOMathArray(new CTOMath[]{ctOMath});
FileOutputStream out = new FileOutputStream("CreateWordFormulaFromMathML.docx");
document.write(out);
out.close();
document.close();
}
}
请注意,此代码需要完整的 ooxml-schemas-*.jar
或 poi-ooxml-full-5.0.0.jar
,如 https://poi.apache.org/faq.html#faq-N10025 中所述。 .
当然有 Java 库可用于将 LaTeX 转换为 MathML。例如:http://www.fmath.info/java/download.jsp .
已下载:fmath-mathml-java-test-project-b1124.zip
并具有 /lib/fmath-mathml-java.jar
和 /lib/jdom-2.0.6.jar
在类路径中,以下工作:
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 org.openxmlformats.schemas.officeDocument.x2006.math.CTR;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.xmlbeans.XmlCursor;
/*
needs the full ooxml-schemas-1.3.jar as mentioned in https://poi.apache.org/faq.html#faq-N10025
*/
public class CreateWordFormulaFromLaTeX {
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();
CTOMathPara ctOMathPara = CTOMathPara.Factory.parse(ooML);
CTOMath ctOMath = ctOMathPara.getOMathArray(0);
//for making this to work with Office 2007 Word also, special font settings are necessary
XmlCursor xmlcursor = ctOMath.newCursor();
while (xmlcursor.hasNextToken()) {
XmlCursor.TokenType tokentype = xmlcursor.toNextToken();
if (tokentype.isStart()) {
if (xmlcursor.getObject() instanceof CTR) {
CTR cTR = (CTR)xmlcursor.getObject();
cTR.addNewRPr2().addNewRFonts().setAscii("Cambria Math");
cTR.getRPr2().getRFonts().setHAnsi("Cambria Math");
}
}
}
return ctOMath;
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("The Pythagorean theorem: ");
String latex = "$a^2 + b^2 = c^2$";
String mathML = fmath.conversion.ConvertFromLatexToMathML.convertToMathML(latex);
mathML = mathML.replaceFirst("<math ", "<math xmlns=\"http://www.w3.org/1998/Math/MathML\" ");
System.out.println(mathML);
CTOMath ctOMath = getOMML(mathML);
System.out.println(ctOMath);
CTP ctp = paragraph.getCTP();
ctp.setOMathArray(new CTOMath[]{ctOMath});
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("The Quadratic Formula: ");
latex = "$x=\\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}$";
mathML = fmath.conversion.ConvertFromLatexToMathML.convertToMathML(latex);
mathML = mathML.replaceFirst("<math ", "<math xmlns=\"http://www.w3.org/1998/Math/MathML\" ");
mathML = mathML.replaceAll("±", "±");
System.out.println(mathML);
ctOMath = getOMML(mathML);
System.out.println(ctOMath);
ctp = paragraph.getCTP();
ctp.setOMathArray(new CTOMath[]{ctOMath});
document.write(new FileOutputStream("CreateWordFormulaFromLaTeX.docx"));
document.close();
}
}
但是每次转换都可能存在错误。因此 LaTeX -> MathML -> OMML 比仅 MathML -> OMML 更容易出错。
在这种情况下,fmath.conversion.ConvertFromLatexToMathML.convertToMathML
会生成没有 namespace 的 Math
XML
。但由于 XSLT
需要这个,因此必须手动添加。
并且 fmath.conversion.ConvertFromLatexToMathML.convertToMathML
使用 HTML
实体,而 MML2OMML.XSL
不知道。因此示例中的“±”必须替换为“±”。
也许SnuggleTeX会是更好的图书馆吗?
下载它并在类路径中添加 snuggletex-core-1.2.2.jar
,我上一个示例中的以下代码更改有效:
...
String latex = "$a^2 + b^2 = c^2$";
uk.ac.ed.ph.snuggletex.SnuggleEngine engine = new uk.ac.ed.ph.snuggletex.SnuggleEngine();
uk.ac.ed.ph.snuggletex.SnuggleSession session = engine.createSession();
uk.ac.ed.ph.snuggletex.SnuggleInput input = new uk.ac.ed.ph.snuggletex.SnuggleInput(latex);
session.parseInput(input);
String mathML = session.buildXMLString();
System.out.println(mathML);
/*
String mathML = fmath.conversion.ConvertFromLatexToMathML.convertToMathML(latex);
mathML = mathML.replaceFirst("<math ", "<math xmlns=\"http://www.w3.org/1998/Math/MathML\" ");
System.out.println(mathML);
*/
CTOMath ctOMath = getOMML(mathML);
System.out.println(ctOMath);
...
latex = "$x=\\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}$";
engine = new uk.ac.ed.ph.snuggletex.SnuggleEngine();
session = engine.createSession();
input = new uk.ac.ed.ph.snuggletex.SnuggleInput(latex);
session.parseInput(input);
mathML = session.buildXMLString();
System.out.println(mathML);
/*
mathML = fmath.conversion.ConvertFromLatexToMathML.convertToMathML(latex);
mathML = mathML.replaceFirst("<math ", "<math xmlns=\"http://www.w3.org/1998/Math/MathML\" ");
mathML = mathML.replaceAll("±", "±");
System.out.println(mathML);
*/
ctOMath = getOMML(mathML);
System.out.println(ctOMath);
...
无需手动干预。至少不使用给定的 LaTeX 示例。
关于java - 使用 Apache POI 在 word (.docx) 中添加 latex 类型方程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46623554/
有没有办法让某些文本仅在 [draft] 选项处于事件状态时显示。 例如,当草稿选项处于事件状态时,我希望在我的标题和摘要之间出现一些文字:“草稿:未经许可不得引用”或诸如此类。 最佳答案 通常这是用
我有一个小问题,我想将 LaTeX 文档的 svn diff 插入到 另一个 LaTeX 文档,目标是显示自修订版 XXX 以来发生的变化。 但是,由于差异包含大量 LaTeX 命令,我无法将其直接包
如何用它们的定义替换所有出现的用户定义的 latex 宏? 例如,给定这个文件 旧的.tex \newcommand{\blah}[2]{#1 \to #2} ... foo \blah{egg}{s
是否可以在 LaTeX 的一个环境 block 中使用多个命令?我试过类似的东西,但没有用...... \begin{sffamily,emph} I'm sans serif and ita
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 8 年前。 Improve
我想将每个项目彼此更靠近,即减少行距,但我没有找到任何有用的东西。 \begin{itemize} \item Processor: Intel Core \textsuperscr
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
我试图在 LaTeX 文档中插入四个数字,但如果我使用 subfigure 命令,我的两个数字保留在第一行,另外两个转到第二行。像这样: 我尝试的另一个解决方案是使用 minipage 命令,但 mi
我将做大量的讲义,然后将它们编译成 LaTeX,这样我就可以拥有出色的文档供将来查看。我正在尝试组织事物,以便我可以拥有一堆包含讲座笔记的小文档,然后在学期结束时将它们编译成包含所有内容的大文档。我过
我有几个引理,其中指定了常量 $C_1$、$C_2$ 等以供以后引用。当然,当我稍后在中间插入一个新的常量定义时,这很烦人。我想要的是一个宏,它可以让我为常量分配标签并为我处理编号。我在想一些事情 %
我想制作一个包含两个目录的 LaTeX 文档,例如: Contents overview 1 - Introduction 2 - Solution Detailed contents 1 - Int
我正在使用 Latex 输入一堆数字 \begin{figure}[h] \centering \subfloat 等等。 如何让 subfloat 数字转到下一页?我的意思是,我输入了大
我在 \documentclass{article}在 latex 。我如何将顾问的名字放在第一页上?我在 latex 中看到过类似 \principaladvisor{} 的例子。但这似乎是通过论文
我目前卡住了,有两个单独的词汇表:main & acronyms . Acronyms词汇表在文本中首次使用时打印脚注,但 main词汇表没有。除了 acronyms 之外,还有什么方法可以制作任何其
如何在 Latex 中定义标签和对自定义环境的相应引用? 例子: \newcounter{fpcounter} \newenvironment{fp}[2] { \stepcounter{fpcoun
我希望doxygen文档生成器根本不生成任何LaTeX文件。 HTML对我来说足够了。是否可以配置doxygen.ini来这样做? 最佳答案 如果使用doxygen.ini是doxygen的配置文件,
我有一个关于 Latex 表的简单对齐问题。在 它看起来如下: \begin{center} \begin{tabular}{| c | l | l | } \hline \tt {
我对 LaTeX 中的定理编号有疑问。我可以按小节编号,例如 Theorem 1.2.1 对于第一节第二小节中的第一个定理。但我需要它给我看 只有小节和定理的编号,而不是节编号,如下所示: Theor
在标题部分中,我引用了文档的各个部分: \section {标题\cite {abc},\cite {def}} 文本 我也在使用目录功能,但是Latex必须首先查看标题(针对目录)中的引文,并为它们
我正在写一个程序(用C语言编写,但我想那不太重要),它与LaTeX中的一些记录 Material 有关。我希望纪录片 Material 包含原始代码中的代码片段。 为了包括源代码并使其保持最新,我在文
我是一名优秀的程序员,十分优秀!