我们正在构建一个java代码,以便使用ApachePOI将word文档(.docx)读取到我们的程序中。当我们在文档中遇到公式和化学方程式时,我们被卡住了。然而,我们设法阅读了公式,但我们不知道如何在相关字符串中找到它的索引。。
输入(格式为*.docx
)
公式前的文本**化学方程**后的文本
我们设计的输出(格式应为HTML
)
公式前文本**化学方程式后文本**
我们无法获取字符串并重建为其原始形式。
问题
现在有没有办法在剥离线内定位图像和公式的位置,以便在重建字符串后可以恢复到原始形式,而不是将其附加到字符串末尾。?
XWPFParagraph paragraph;
for (CTOMath ctomath : paragraph.getCTP().getOMathList()) {
formulas=formulas + getMathML(ctomath);
}
如果需要的格式是超文本标记语言
,那么Word
文本内容连同Office MathML方程可以通过以下方式读取。
在阅读方程式
如果你想把那些OMath
元素与段落中的其他元素放在上下文中,那么就使用org。阿帕奇。xmlbeans。XmlCursor
需要循环遍历段落中所有不同的XML
元素。下面的示例使用XmlCursor
从段落中获取与OMath
元素一起运行的文本。
从Office MathML
到MathML的转换使用与Reading方程相同的XSLT
方法
文件公式。docx
看起来像:
代码:
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.apache.xmlbeans.XmlCursor;
import org.w3c.dom.Node;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.Desktop;
import java.util.List;
import java.util.ArrayList;
/*
needs the full ooxml-schemas-1.4.jar as mentioned in https://poi.apache.org/faq.html#faq-N10025
*/
public class WordReadTextWithFormulasAsHTML {
static File stylesheet = new File("OMML2MML.XSL");
static TransformerFactory tFactory = TransformerFactory.newInstance();
static StreamSource stylesource = new StreamSource(stylesheet);
//method for getting MathML from oMath
static String getMathML(CTOMath ctomath) throws Exception {
Transformer transformer = tFactory.newTransformer(stylesource);
Node node = ctomath.getDomNode();
DOMSource source = new DOMSource(node);
StringWriter stringwriter = new StringWriter();
StreamResult result = new StreamResult(stringwriter);
transformer.setOutputProperty("omit-xml-declaration", "yes");
transformer.transform(source, result);
String mathML = stringwriter.toString();
stringwriter.close();
//The native OMML2MML.XSL transforms OMML into MathML as XML having special name spaces.
//We don't need this since we want using the MathML in HTML, not in XML.
//So ideally we should changing the OMML2MML.XSL to not do so.
//But to take this example as simple as possible, we are using replace to get rid of the XML specialities.
mathML = mathML.replaceAll("xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"", "");
mathML = mathML.replaceAll("xmlns:mml", "xmlns");
mathML = mathML.replaceAll("mml:", "");
return mathML;
}
//method for getting HTML including MathML from XWPFParagraph
static String getTextAndFormulas(XWPFParagraph paragraph) throws Exception {
StringBuffer textWithFormulas = new StringBuffer();
//using a cursor to go through the paragraph from top to down
XmlCursor xmlcursor = paragraph.getCTP().newCursor();
while (xmlcursor.hasNextToken()) {
XmlCursor.TokenType tokentype = xmlcursor.toNextToken();
if (tokentype.isStart()) {
if (xmlcursor.getName().getPrefix().equalsIgnoreCase("w") && xmlcursor.getName().getLocalPart().equalsIgnoreCase("r")) {
//elements w:r are text runs within the paragraph
//simply append the text data
textWithFormulas.append(xmlcursor.getTextValue());
} else if (xmlcursor.getName().getLocalPart().equalsIgnoreCase("oMath")) {
//we have oMath
//append the oMath as MathML
textWithFormulas.append(getMathML((CTOMath)xmlcursor.getObject()));
}
} else if (tokentype.isEnd()) {
//we have to check whether we are at the end of the paragraph
xmlcursor.push();
xmlcursor.toParent();
if (xmlcursor.getName().getLocalPart().equalsIgnoreCase("p")) {
break;
}
xmlcursor.pop();
}
}
return textWithFormulas.toString();
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("Formula.docx"));
//using a StringBuffer for appending all the content as HTML
StringBuffer allHTML = new StringBuffer();
//loop over all IBodyElements - should be self explained
for (IBodyElement ibodyelement : document.getBodyElements()) {
if (ibodyelement.getElementType().equals(BodyElementType.PARAGRAPH)) {
XWPFParagraph paragraph = (XWPFParagraph)ibodyelement;
allHTML.append("<p>");
allHTML.append(getTextAndFormulas(paragraph));
allHTML.append("</p>");
} else if (ibodyelement.getElementType().equals(BodyElementType.TABLE)) {
XWPFTable table = (XWPFTable)ibodyelement;
allHTML.append("<table border=1>");
for (XWPFTableRow row : table.getRows()) {
allHTML.append("<tr>");
for (XWPFTableCell cell : row.getTableCells()) {
allHTML.append("<td>");
for (XWPFParagraph paragraph : cell.getParagraphs()) {
allHTML.append("<p>");
allHTML.append(getTextAndFormulas(paragraph));
allHTML.append("</p>");
}
allHTML.append("</td>");
}
allHTML.append("</tr>");
}
allHTML.append("</table>");
}
}
document.close();
//creating a sample HTML file
String encoding = "UTF-8";
FileOutputStream fos = new FileOutputStream("result.html");
OutputStreamWriter writer = new OutputStreamWriter(fos, encoding);
writer.write("<!DOCTYPE html>\n");
writer.write("<html lang=\"en\">");
writer.write("<head>");
writer.write("<meta charset=\"utf-8\"/>");
//using MathJax for helping all browsers to interpret MathML
writer.write("<script type=\"text/javascript\"");
writer.write(" async src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=MML_CHTML\"");
writer.write(">");
writer.write("</script>");
writer.write("</head>");
writer.write("<body>");
writer.write(allHTML.toString());
writer.write("</body>");
writer.write("</html>");
writer.close();
Desktop.getDesktop().browse(new File("result.html").toURI());
}
}
结果:
刚刚使用ApachePOI5.0.0对这段代码进行了测试,它运行正常。您需要poi-ooxml-full-5.0.0。jar
用于apache poi 5.0.0。请阅读https://poi.apache.org/help/faq.html#faq-N10025 for whatooxml
库对于whatapache poi
版本是必需的。
我正在使用库python-docx解析docx文件。我需要阅读文档和段落的标题,但是我在文档中找不到任何关于文档标题的东西。有关于将标头写入新文件的文档,但没有关于读取标头的文档。有办法做到这一点吗?
我正在尝试创建一个包含多列的word文档。这样做(而不是使用表)的原因是,数据将跨越多个页面,在添加到新页面之前,我只能用列填充整个页面。 可以用ApachePOI实现吗?谢谢
我面临的例外情况如下: java.lang.nosuchmethoderror:org.apache.xml.utils.DefaulTerrorHandler.(Z)V在org.docx4j.org.apache.xalan.transformer.transformerIdentityImpl.(TransformerIdentityImpl.transformerIdentityImpl.(
我是编程界的新手。嗯,我正在尝试使用ApachePOI库读取excel文件(5行5列)。我实际上有两个相同问题的实现。在第一个代码片段中,我只是读取excel文件并将其打印到控制台中。 然而,现在我正试图将读取的excel数据保存到一个数组中。所以我想在动态获取excel行和列大小后设置数组大小。但令我惊讶的是,当我执行第二个代码段时,似乎“while(cellIterator.hasNext()
我还没有找到任何方法来做到这一点。你能给我提点建议吗。
我正在阅读一个word文件,使用Python在文档中有许多表。我只需要从某些表中提取数据,这取决于它们出现的部分。有没有办法通过文件搜索,到达某一行,读取该行后面出现的表格? 例如,如果文档这个词类似于: 1 2 3 [表格] 4 5 6 [表格] 我能在“6”之后阅读表格吗? 读取“第二个表”不起作用,因为出现在该表之前的表的数量是任意的;我需要读它,因为它出现在“6”之后。