如何在JDOM2中为<start>与<stop>间元素创建最高层级XML父元素
JDOM2中为与间的元素创建最高层级父节点
需求:在JDOM2结构里,给位于<start>和<stop>两个边界元素之间的所有元素,创建尽可能最高层级的新XML父元素(示例中父元素名为<added>),<start>和<stop>可以放在任意位置。
简化示例
输入XML
<root> <a> <ax> <start></start> </ax> <ay></ay> <az></az> </a> <b> <bx></bx> </b> <c> <cx></cx> <cy></cy> <cz> <cza></cza> <czb> <stop></stop> </czb> </cz> </c> </root>
输出XML
<root> <a> <ax> <start></start> </ax> <added> <ay></ay> <az></az> </added> </a> <added> <b> <bx></bx> </b> </added> <c> <added> <cx></cx> <cy></cy> </added> <cz> <added> <cza></cza> </added> <czb> <stop></stop> </czb> </cz> </c> </root>
实现方案
核心思路
- 定位
<start>和<stop>元素,筛选出两者之间的所有目标元素 - 对每个目标元素,向上查找不包含
<start>或<stop>的最顶层父节点,这就是能包裹它的最高层级 - 在该父节点下创建
<added>元素,把同一层级的目标元素都移动进去,避免重复创建父元素
JDOM2代码实现
import org.jdom2.*; import org.jdom2.filter.Filters; import org.jdom2.xpath.XPathExpression; import org.jdom2.xpath.XPathFactory; import java.util.List; import java.util.Optional; public class WrapBetweenStartStop { public static void main(String[] args) throws JDOMException { // 这里假设你已经加载好XML文档到Document对象 Document doc = getSampleDocument(); XPathFactory xpf = XPathFactory.instance(); // 找到start和stop元素 Element start = xpf.compile("//start", Filters.element()).evaluateFirst(doc); Element stop = xpf.compile("//stop", Filters.element()).evaluateFirst(doc); if (start == null || stop == null) { System.out.println("未找到start或stop元素"); return; } // 筛选出start之后、stop之前的所有元素(排除自身) List<Element> targetElements = xpf.compile( "//*[preceding::start and following::stop]", Filters.element()) .evaluate(doc); // 遍历处理每个目标元素 for (Element elem : targetElements) { Element highestParent = findHighestValidParent(elem, start, stop); // 检查当前父节点下是否已有added元素,没有则创建 Element added = findOrCreateAddedElement(highestParent, elem); // 把元素移到added里 elem.detach(); added.addContent(elem); } // 输出处理后的XML XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); try { outputter.output(doc, System.out); } catch (Exception e) { e.printStackTrace(); } } // 找到不包含start/stop的最高层级父节点 private static Element findHighestValidParent(Element elem, Element start, Element stop) { Element current = elem.getParentElement(); Element lastValid = elem.getParentElement(); while (current != null) { // 检查当前父节点是否包含start或stop boolean hasStart = current.getDescendants(Filters.element()) .anyMatch(e -> e.equals(start)); boolean hasStop = current.getDescendants(Filters.element()) .anyMatch(e -> e.equals(stop)); if (hasStart || hasStop) { break; } lastValid = current; current = current.getParentElement(); } return lastValid; } // 在指定父节点下查找或创建added元素,插入到目标元素的原位置 private static Element findOrCreateAddedElement(Element parent, Element target) { // 先找已有的added元素 Optional<Element> existingAdded = parent.getChildren("added").stream().findFirst(); if (existingAdded.isPresent()) { return existingAdded.get(); } // 创建新的added元素,插入到目标元素原来的位置 Element added = new Element("added"); int index = parent.indexOf(target); parent.addContent(index, added); return added; } // 生成示例文档(仅用于测试) private static Document getSampleDocument() { Element root = new Element("root"); Element a = new Element("a"); Element ax = new Element("ax").addContent(new Element("start")); a.addContent(ax).addContent(new Element("ay")).addContent(new Element("az")); Element b = new Element("b").addContent(new Element("bx")); Element c = new Element("c"); Element cz = new Element("cz").addContent(new Element("cza")); Element czb = new Element("czb").addContent(new Element("stop")); cz.addContent(czb); c.addContent(new Element("cx")).addContent(new Element("cy")).addContent(cz); root.addContent(a).addContent(b).addContent(c); return new Document(root); } }
代码说明
findHighestValidParent:向上遍历父节点,直到遇到包含<start>或<stop>的节点,返回之前的最后一个有效父节点,保证包裹层级最高findOrCreateAddedElement:避免在同一父节点下重复创建<added>元素,同时保持目标元素的原有顺序- XPath筛选:精准定位出
<start>和<stop>之间的所有元素,确保只处理目标节点
内容的提问来源于stack exchange,提问作者marianogaccio
相关产品推荐
相关产品推荐

