为什么使用 CTSectPr.Factory.parse 方法解析 xml 标签出现两个 <w:sectPr> 标签嵌套
Why use the CTSectPr.Factory.parse method to parse xml labels appear nested by two <w:sectPr> tags
我要在要分节的文档中创建 < w:sectPr > 标签。
我有一堆xml个字符:
String defaultSectPr =
"<w:sectPr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">"
+"<w:pgSz w:w=\"11906\" w:h=\"16838\"/>"
+"<w:pgMar w:top=\"1701\" w:right=\"1134\" w:bottom=\"1418\" w:left=\"1418\""
+" w:header=\"1185\" w:footer=\"913\" w:gutter=\"0\"/>"
+"<w:cols w:space=\"425\"/>"
+"<w:pgNumType w:start=\"1\"/>"
+"<w:docGrid w:type=\"lines\" w:linePitch=\"312\" w:charSpace=\"0\"/>"
+"</w:sectPr>";
而我想用它来创建标签,所以我使用了以下代码:
String defaultSectPr =
"<w:sectPr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">"
+"<w:pgSz w:w=\"11906\" w:h=\"16838\"/>"
+"<w:pgMar w:top=\"1701\" w:right=\"1134\" w:bottom=\"1418\" w:left=\"1418\""
+" w:header=\"1185\" w:footer=\"913\" w:gutter=\"0\"/>"
+"<w:cols w:space=\"425\"/>"
+"<w:pgNumType w:start=\"1\"/>"
+"<w:docGrid w:type=\"lines\" w:linePitch=\"312\" w:charSpace=\"0\"/>"
+"</w:sectPr>";
CTSectPr ctSectPr = null;
try {
ctSectPr = CTSectPr.Factory.parse(defaultSectPr);
System.out.println(ctSectPr);
} catch (XmlException e) {
e.printStackTrace();
}
List<CTP> ctps = ctBody.getPList();
for(CTP ctp : ctps){
// Get the ctppr label and determine if there is a selectPr label included
if(ctp.isSetPPr()){
CTPPr ctpPr = ctp.getPPr();
if(ctpPr.isSetSectPr()){
ctpPr.unsetSectPr();
// Create a selectPr label
ctpPr.setSectPr(ctSectPr);
}
}
但我得到的结果是这样的:
<w:sectPr>
<w:sectPr>
<w:pgSz w:w="11906" w:h="16838"/>
<w:pgMar w:top="1701" w:right="1134" w:bottom="1418" w:left="1418" w:header="1185" w:footer="913" w:gutter="0"/>
<w:cols w:space="425"/>
<w:pgNumType w:start="1"/>
<w:docGrid w:type="lines" w:linePitch="312" w:charSpace="0"/>
</w:sectPr>
</w:sectPr>
我不确定问题是否在于对 CtSectPr 对象使用字符串解析,所以我使用方法来构建标签:
CTSectPr sectPr = ctpPr.getSectPr();
CTPageSz ctPageSz = sectPr.addNewPgSz();
ctPageSz.setW(BigInteger.valueOf(11906l));
ctPageSz.setH(BigInteger.valueOf(16838l));
CTPageMar ctPageMar = sectPr.addNewPgMar();
ctPageMar.setTop(BigInteger.valueOf(1701l));
ctPageMar.setRight(BigInteger.valueOf(1134l));
ctPageMar.setBottom(BigInteger.valueOf(1418l));
ctPageMar.setLeft(BigInteger.valueOf(1418l));
ctPageMar.setHeader(BigInteger.valueOf(1185l));
ctPageMar.setFooter(BigInteger.valueOf(913l));
ctPageMar.setGutter(BigInteger.valueOf(0l));
sectPr.addNewCols().setSpace(BigInteger.valueOf(452l));
sectPr.addNewPgNumType().setStart(BigInteger.valueOf(1l));
CTDocGrid ctDocGrid = sectPr.addNewDocGrid();
ctDocGrid.setType(STDocGrid.LINES);
ctDocGrid.setLinePitch(BigInteger.valueOf(312l));
ctDocGrid.setCharSpace(BigInteger.valueOf(0l));
没错:
<w:sectPr>
<w:pgSz w:w="11906" w:h="16838"/>
<w:pgMar w:top="1701" w:right="1134" w:bottom="1418" w:left="1418" w:header="1185" w:footer="913"
w:gutter="0"/>
<w:pgNumType w:start="1"/>
<w:cols w:space="452"/>
<w:docGrid w:type="lines" w:linePitch="312" w:charSpace="0"/>
</w:sectPr>
所以我猜这里有问题(不知道对不对):
ctSectPr = CTSectPr.Factory.parse(defaultSectPr);
感谢Axel Richter的回答,确实解决了我的问题,也为解析xml标签到poi这个方向提供了思路。
XmlObject.Factory.parse
方法期望从 XML 中解析一个对象,它是 XML 元素的 content(内部 XML).但是您的 String defaultSectPr
包含 CTSectPr
.
的外部 XML
一些主要的根 OOXML
元素有特殊的 *Document
对象。这些可以从整个文档 XML 中解析出来,然后只提供获取单个根元素的方法。例如 CommentsDocument
提供 CTComments getComments()
.
当然CTSectPr
没有这样的文档元素。但是可以从 CTSectPr
的外部 XML 解析 CTSectPr
的父元素之一,然后从父元素的 getSectPr()
方法中获取 CTSectPr
元素。例如 CTPPr
是 CTSectPr
的父元素并提供 getSectPr()
.
示例:
...
CTSectPr ctSectPr = null;
try {
CTPPr ctPPr = CTPPr.Factory.parse(defaultSectPr);
ctSectPr = ctPPr.getSectPr();
System.out.println(ctSectPr);
} catch (Exception e) {
e.printStackTrace();
}
...
我要在要分节的文档中创建 < w:sectPr > 标签。
我有一堆xml个字符:
String defaultSectPr =
"<w:sectPr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">"
+"<w:pgSz w:w=\"11906\" w:h=\"16838\"/>"
+"<w:pgMar w:top=\"1701\" w:right=\"1134\" w:bottom=\"1418\" w:left=\"1418\""
+" w:header=\"1185\" w:footer=\"913\" w:gutter=\"0\"/>"
+"<w:cols w:space=\"425\"/>"
+"<w:pgNumType w:start=\"1\"/>"
+"<w:docGrid w:type=\"lines\" w:linePitch=\"312\" w:charSpace=\"0\"/>"
+"</w:sectPr>";
而我想用它来创建标签,所以我使用了以下代码:
String defaultSectPr =
"<w:sectPr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">"
+"<w:pgSz w:w=\"11906\" w:h=\"16838\"/>"
+"<w:pgMar w:top=\"1701\" w:right=\"1134\" w:bottom=\"1418\" w:left=\"1418\""
+" w:header=\"1185\" w:footer=\"913\" w:gutter=\"0\"/>"
+"<w:cols w:space=\"425\"/>"
+"<w:pgNumType w:start=\"1\"/>"
+"<w:docGrid w:type=\"lines\" w:linePitch=\"312\" w:charSpace=\"0\"/>"
+"</w:sectPr>";
CTSectPr ctSectPr = null;
try {
ctSectPr = CTSectPr.Factory.parse(defaultSectPr);
System.out.println(ctSectPr);
} catch (XmlException e) {
e.printStackTrace();
}
List<CTP> ctps = ctBody.getPList();
for(CTP ctp : ctps){
// Get the ctppr label and determine if there is a selectPr label included
if(ctp.isSetPPr()){
CTPPr ctpPr = ctp.getPPr();
if(ctpPr.isSetSectPr()){
ctpPr.unsetSectPr();
// Create a selectPr label
ctpPr.setSectPr(ctSectPr);
}
}
但我得到的结果是这样的:
<w:sectPr>
<w:sectPr>
<w:pgSz w:w="11906" w:h="16838"/>
<w:pgMar w:top="1701" w:right="1134" w:bottom="1418" w:left="1418" w:header="1185" w:footer="913" w:gutter="0"/>
<w:cols w:space="425"/>
<w:pgNumType w:start="1"/>
<w:docGrid w:type="lines" w:linePitch="312" w:charSpace="0"/>
</w:sectPr>
</w:sectPr>
我不确定问题是否在于对 CtSectPr 对象使用字符串解析,所以我使用方法来构建标签:
CTSectPr sectPr = ctpPr.getSectPr();
CTPageSz ctPageSz = sectPr.addNewPgSz();
ctPageSz.setW(BigInteger.valueOf(11906l));
ctPageSz.setH(BigInteger.valueOf(16838l));
CTPageMar ctPageMar = sectPr.addNewPgMar();
ctPageMar.setTop(BigInteger.valueOf(1701l));
ctPageMar.setRight(BigInteger.valueOf(1134l));
ctPageMar.setBottom(BigInteger.valueOf(1418l));
ctPageMar.setLeft(BigInteger.valueOf(1418l));
ctPageMar.setHeader(BigInteger.valueOf(1185l));
ctPageMar.setFooter(BigInteger.valueOf(913l));
ctPageMar.setGutter(BigInteger.valueOf(0l));
sectPr.addNewCols().setSpace(BigInteger.valueOf(452l));
sectPr.addNewPgNumType().setStart(BigInteger.valueOf(1l));
CTDocGrid ctDocGrid = sectPr.addNewDocGrid();
ctDocGrid.setType(STDocGrid.LINES);
ctDocGrid.setLinePitch(BigInteger.valueOf(312l));
ctDocGrid.setCharSpace(BigInteger.valueOf(0l));
没错:
<w:sectPr>
<w:pgSz w:w="11906" w:h="16838"/>
<w:pgMar w:top="1701" w:right="1134" w:bottom="1418" w:left="1418" w:header="1185" w:footer="913"
w:gutter="0"/>
<w:pgNumType w:start="1"/>
<w:cols w:space="452"/>
<w:docGrid w:type="lines" w:linePitch="312" w:charSpace="0"/>
</w:sectPr>
所以我猜这里有问题(不知道对不对):
ctSectPr = CTSectPr.Factory.parse(defaultSectPr);
感谢Axel Richter的回答,确实解决了我的问题,也为解析xml标签到poi这个方向提供了思路。
XmlObject.Factory.parse
方法期望从 XML 中解析一个对象,它是 XML 元素的 content(内部 XML).但是您的 String defaultSectPr
包含 CTSectPr
.
一些主要的根 OOXML
元素有特殊的 *Document
对象。这些可以从整个文档 XML 中解析出来,然后只提供获取单个根元素的方法。例如 CommentsDocument
提供 CTComments getComments()
.
当然CTSectPr
没有这样的文档元素。但是可以从 CTSectPr
的外部 XML 解析 CTSectPr
的父元素之一,然后从父元素的 getSectPr()
方法中获取 CTSectPr
元素。例如 CTPPr
是 CTSectPr
的父元素并提供 getSectPr()
.
示例:
...
CTSectPr ctSectPr = null;
try {
CTPPr ctPPr = CTPPr.Factory.parse(defaultSectPr);
ctSectPr = ctPPr.getSectPr();
System.out.println(ctSectPr);
} catch (Exception e) {
e.printStackTrace();
}
...