You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用XPATH或Apache POI从XML中过滤提取水印文本?

Apache POI获取DOCX文档水印的实现方法

方法1:使用现有XPATH准确获取水印值

你写的XPATH本身逻辑正确,只需要补充命名空间声明即可正常执行,POI的XPATH查询要求显式声明所有用到的XML前缀对应的命名空间URI:

import org.apache.xmlbeans.XmlObject;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import java.io.File;
import java.io.FileInputStream;

public class WatermarkReader {
    public static void main(String[] args) throws Exception {
        File docxFile = new File("你的文档路径.docx");
        XWPFDocument document = new XWPFDocument(new FileInputStream(docxFile));
        XWPFHeaderFooterPolicy headerFooterPolicy = document.getHeaderFooterPolicy();
        XWPFHeader defaultHeader = headerFooterPolicy.getDefaultHeader();
        
        // XPATH开头声明v前缀对应的命名空间
        String xpath = "declare namespace v='urn:schemas-microsoft-com:vml'; " +
                "string(//v:shape[contains(@id,'PowerPlusWaterMarkObject')]/v:textpath/@string)";
        
        XmlObject[] results = defaultHeader._getHdrFtr().selectPath(xpath);
        if (results != null && results.length > 0) {
            String watermarkText = results[0].newCursor().getTextValue();
            System.out.println("水印内容:" + watermarkText);
        }
        document.close();
    }
}

方法1注意事项:

  • 命名空间URI必须和你打印的XML里xmlns:v的取值完全一致,否则查询返回空
  • 仅适配Word默认插入的文本水印,自定义插入的图形水印可能需要调整匹配条件

方法2:遍历Header节点获取水印(兼容性更好)

如果不想依赖XPATH,也可以直接遍历Header内的所有VML图形节点,通过POI封装的对象方法读取水印内容,同时支持覆盖所有页面类型的水印:

import com.microsoft.schemas.vml.CTShape;
import com.microsoft.schemas.vml.CTTextPath;
import org.apache.xmlbeans.XmlObject;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

public class WatermarkReader {
    public static void main(String[] args) throws Exception {
        File docxFile = new File("你的文档路径.docx");
        XWPFDocument document = new XWPFDocument(new FileInputStream(docxFile));
        XWPFHeaderFooterPolicy headerFooterPolicy = document.getHeaderFooterPolicy();
        
        // 收集所有类型的Header,避免遗漏首页、偶数页的特殊水印
        List<XWPFHeader> allHeaders = new ArrayList<>();
        if (headerFooterPolicy.getDefaultHeader() != null) allHeaders.add(headerFooterPolicy.getDefaultHeader());
        if (headerFooterPolicy.getFirstPageHeader() != null) allHeaders.add(headerFooterPolicy.getFirstPageHeader());
        if (headerFooterPolicy.getEvenPageHeader() != null) allHeaders.add(headerFooterPolicy.getEvenPageHeader());
        
        for (XWPFHeader header : allHeaders) {
            XmlObject[] shapeObjs = header._getHdrFtr().selectPath("declare namespace v='urn:schemas-microsoft-com:vml'; //v:shape");
            for (XmlObject shapeObj : shapeObjs) {
                CTShape shape = CTShape.Factory.parse(shapeObj.newInputStream());
                // 匹配水印专属shape id前缀
                if (shape.getId() != null && shape.getId().contains("PowerPlusWaterMarkObject")) {
                    CTTextPath textPath = shape.getTextPath();
                    if (textPath != null) {
                        String watermarkText = textPath.getString();
                        System.out.println("水印内容:" + watermarkText);
                    }
                    // 如需识别图片水印,可读取shape.getFill().getSrc()属性获取图片资源
                }
            }
        }
        document.close();
    }
}

方法2优势:

  • 覆盖所有页面类型的水印设置,不会遗漏特殊配置的首页、偶数页水印
  • 同时支持文本水印、图片水印的识别,扩展性更强
  • 直接调用POI封装的对象方法,稳定性高于纯XPATH字符串查询

内容的提问来源于stack exchange,提问作者Sahib Yar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 04:45:03