为什么使用 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元素。例如 CTPPrCTSectPr 的父元素并提供 getSectPr().

示例:

...
CTSectPr ctSectPr = null;
try {
    CTPPr ctPPr = CTPPr.Factory.parse(defaultSectPr);
    ctSectPr = ctPPr.getSectPr();
    System.out.println(ctSectPr);
} catch (Exception e) {
    e.printStackTrace();
}
...