Разделение XML с использованием JDOM Java

У меня есть следующая строка XML.

<Engineers>
    <Engineer>
        <Name>JOHN</Name>
        <Position>STL</Position>
        <Team>SS</Team>
    </Engineer>
    <Engineer>
        <Name>UDAY</Name>
        <Position>TL</Position>
        <Team>SG</Team>
    </Engineer>
    <Engineer>
        <Name>INDRA</Name>
        <Position>Director</Position>
        <Team>PP</Team>
    </Engineer>
</Engineers>

Мне нужно разделить этот XML-файл на более мелкие XML-строки, когда Xpath указан как Engineers/Enginner.

Меньшие строки XML следующие

    <Engineer>
        <Name>INDRA</Name>
        <Position>Director</Position>
        <Team>PP</Team>
    </Engineer>

<Engineer>
        <Name>JOHN</Name>
        <Position>STL</Position>
        <Team>SS</Team>
 </Engineer>

Я реализовал следующее, используя saxon xpath и JDOM.

import net.sf.saxon.Configuration;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.DocumentInfo;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.s9api.DocumentBuilder;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.xpath.XPathFactoryImpl;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.junit.Test;
import org.xml.sax.InputSource;

import java.io.File;
import java.io.FileInputStream;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;

 public void testXML() throws XPathFactoryConfigurationException, XPathExpressionException, Exception {

        System.setProperty("javax.xml.xpath.XPathFactory:" + NamespaceConstant.OBJECT_MODEL_JDOM,
                "net.sf.saxon.xpath.XPathFactoryImpl");
        XPathFactory xPathFactory = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_JDOM);
        XPath xPath = xPathFactory.newXPath();
        InputSource inputSource = new InputSource(new File(filename).toURI().toString());
        SAXSource saxSource = new SAXSource(inputSource);
        Configuration config = ((XPathFactoryImpl) xPathFactory).getConfiguration();
        DocumentInfo document = config.buildDocument(saxSource);
        XPathExpression xPathExpression = xPath.compile("//Engineers/Engineer");
        List matches = (List) xPathExpression.evaluate(document, XPathConstants.NODESET);
        if (matches != null) {
            for (Iterator iter = matches.iterator(); iter.hasNext(); ) {
                NodeInfo node = (NodeInfo) iter.next();
                System.out.println(node.getDisplayName() + " - " + node.getStringValue());
            }
        }

    }

Это дает следующий результат.

Engineer - 
        JOHN
        STL
        SS

Engineer - 
        UDAY
        TL
        SG

Engineer - 
        INDRA
        Director
        PP

Как я могу изменить код, чтобы получить желаемый результат? Или есть способ получить имена дочерних атрибутов (имя, должность, команда) внутри Engineer

2 ответа

Я бы сделал разделение в XSLT:

<xsl:stylesheet ....>
<xsl:template match="Engineeers/Engineer">
  <xsl:result-document href="{position()}.xml">
    <xsl:copy-of select="."/>
  </xsl:result-document>
</xsl:template>
</xsl:stylesheet>

Если вы хотите получить результат в виде списка документов JDOM, вы можете предоставить Saxon OutputURIResolver:

Controller controller = transformer.getUnderlyingController();
final Configuration config = controller.getConfiguration();
List<Document> jdomDocuments = new ArrayLis<Document>();
Controller.setOutputURIResolver(new OutputURIResolver() {

   public Result resolve(href, base) {
       return new JDOM2Writer(config.makePipelineConfiguration());
   }

   public void close(Result result) {
       jdomDocuments.add(((JDOM2Writer)result).getDocument());
   }
}

и по завершении результаты будут в jdomDocuments,

Если вы используете JDOM для этой работы, вам следует рассмотреть возможность использования собственных методов JDOM вместо абстракции, выполняемой через Saxon.

Рассмотрим что-то вроде:

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.xpath.XPathFactory;
import org.jdom2.xpath.XPAthExpression;
import org.jdom2.output.XMLOutputter;
import org.jdom2.input.SAXBuilder;
import org.jdom2.filter.Filters;

....

    XPathExpression xpe = XPathFactory.instance()
         .compile("//Engineers/Engineer", Filters.element());

    Document doc = new SAXBuilder().build(new File(filename));

    XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat());

    for (Element e : xpe.evaluate(doc)) {
        xout.output(e, System.out);
    }
Другие вопросы по тегам