2016-05-12 18 views
0

Betrachten Sie die XML-Datei, Report.xml:Splitting eine größere Größe XML-Datei mit Java (Beibehaltung der Eltern Attribute und Geschwister)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <Report FileName="abc.bin" reportDate="05/12/2016 02:44:22 AM"> 
     <Statistics> 
     <child value="abc"> 
     <subchild>...</subchild> 
     </child> 
     <child value="xyz"> 
     <subchild>...</subchild> 
     </child> 
     </Statistics> 
     <Properties> 
     <child1>...</child1> 
     <child2>...</child2> 
     . 
     . 
     . 
     <childn>...</childn> 
     </Properties> 
     <OverallStatistics> 
     <child1>...</child1> 
     <child2>...</child2> 
     . 
     . 
     . 
     <childn>...</child1> 
     </OverallStatistics> 
    </Report> 

Ich möchte nur die oben XML-Datei als aufzuspalten:

ReportSplit1 .xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<Report FileName="abc.bin" reportDate="05/12/2016 02:44:22 AM"> 
    <Statistics> 
     <child value="abc"> 
     <subchild>...</subchild> 
     </child> 
    </Statistics> 
    <Properties> 
     <child1>...</child1> 
     <child2>...</child2> 
     . 
     . 
     . 
     <childn>...</childn> 
    </Properties> 
    <OverallStatistics> 
     <child1>...</child1> 
     <child2>...</child2> 
     . 
     . 
     . 
     <childn>...</child1> 
    </OverallStatistics> 
</Report> 

ReportSplit2.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<Report FileName="abc.bin" reportDate="05/12/2016 02:44:22 AM"> 
    <Statistics> 
     <child value="xyz"> 
     <subchild>...</subchild> 
     </child> 
    </Statistics> 
    <Properties> 
     <child1>...</child1> 
     <child2>...</child2> 
     . 
     . 
     . 
     <childn>...</childn> 
    </Properties> 
    <OverallStatistics> 
     <child1>...</child1> 
     <child2>...</child2> 
     . 
     . 
     . 
     <childn>...</child1> 
    </OverallStatistics> 
</Report> 

, d.h. Beibehalten der Attribute des Elternknotens und Beibehalten der Geschwisterknoten. Die Aufteilung sollte nur für die untergeordneten Knoten im Statistikknoten vorgenommen werden.

Gefolgt die im link durch Änderung der Schnipsel als

package xmlsplitting; 
import java.io.*; 
import java.util.ArrayList; 
import java.util.List; 
import javax.xml.parsers.*; 
import org.w3c.dom.*; 
import org.xml.sax.*; 
import javax.xml.transform.*; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.xpath.*; 
public class XmlSplit 
{ 
    static public void main(String[] arg) throws Exception 
    { 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     Document doc = builder.parse("D:\\Analyzer\\FileSplit\\Report.xml"); 
     TransformerFactory tranFactory = TransformerFactory.newInstance(); 
     Transformer aTransformer = tranFactory.newTransformer(); 
     XPath xpath = XPathFactory.newInstance().newXPath(); 
     NodeList list = (NodeList)xpath.evaluate("//Report/Statistics/child", doc, XPathConstants.NODESET); 
     for (int i=1; i<list.getLength(); i++) 
     { 
      Node element = list.item(i).cloneNode(true); 
      if(element.hasChildNodes()) 
      { 
        Source src = new DOMSource(element); 
        FileOutputStream fs = new FileOutputStream("D:\\Analyzer\\FileSplit\\ReportSplit"+ i + ".xml"); 
        Result dest = new StreamResult(fs); 
        aTransformer.transform(src, dest); 
        fs.close(); 
      } 
     } 
    } 
} 

Die erzielten XML-Dateien Splits sind gegeben Abhilfe:

ReportSplit1.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <child value="abc"> 
     <subchild>...</subchild> 
    </child> 

ReportSplit2.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <child value="xyz"> 
     <subchild>...</subchild> 
    </child> 

Kann jemand eine Problemumgehung bereitstellen, um die gewünschten XML-Dateiaufteilungen zu erreichen?

Antwort

0

Verwenden Sie XSLT, die deklarative, spezielle Programmiersprache, um XML-Dokumente anstelle von XPath zu transformieren, da Sie die gesamte Dokumentumwandlung benötigen. Für Ihre Zwecke, ein eingebetteter, dynamischer XSLT Run auf einer Schleife von Werten ausgeben kann mehr XML-Dateien:

XSLT Script (unten eingebettet Beispiel verwendet ‚abc‘, die iterativ verwendet wird und ersetzt) ​​

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output version="1.0" encoding="UTF-8" indent="yes" /> 
<xsl:strip-space elements="*"/> 

    <!-- Identity Transform --> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="child[not(@value='abc')]"/> 

</xsl:transform> 

Java Script

import javax.xml.parsers.*; 
import javax.xml.transform.*; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.transform.OutputKeys; 

import java.io.*; 
import java.net.URISyntaxException; 

import org.w3c.dom.Document; 
import org.xml.sax.SAXException; 
public class XmlSplit { 
    public static void main(String[] args) throws IOException, URISyntaxException, 
                SAXException, ParserConfigurationException, 
                TransformerException { 

     // Load XML Source 
     String inputXML = "/path/to/XMLSource.xml"; 

     // Declare XML Values Array 
     String[] xmlVals = {"abc", "xyz"}; 

     // Iterate through Values running dynamic, embedded XSLT 
     for (String s: xmlVals) { 
      String outputXML = "/path/to/output_" + s + ".xml"; 

      String xslStr = String.join("\n", 
       "<xsl:transform xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">", 
       "<xsl:output version=\"1.0\" encoding=\"UTF-8\" indent=\"yes\" />", 
       "<xsl:strip-space elements=\"*\"/>", 
       "<xsl:template match=\"@*|node()\">", 
       "<xsl:copy>", 
       "<xsl:apply-templates select=\"@*|node()\"/>", 
       "</xsl:copy>", 
       "</xsl:template>", 
       "<xsl:template match=\"child[not(@value='"+ s +"')]\"/>", 
       "</xsl:transform>"); 

      Source xslt = new StreamSource(new StringReader(xslStr));    
      DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();    
      DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); 
      Document doc = docBuilder.parse (new File(inputXML)); 

      // XSLT Transformation with pretty print 
      TransformerFactory prettyPrint = TransformerFactory.newInstance(); 
      Transformer transformer = prettyPrint.newTransformer(xslt); 

      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); 
      transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); 
      transformer.setOutputProperty(OutputKeys.METHOD, "xml"); 
      transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
      transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 
      transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");       

      // Output Result to File 
      DOMSource source = new DOMSource(doc); 
      StreamResult result = new StreamResult(new File(outputXML));   
      transformer.transform(source, result); 
     } 

    } 
} 
0

Ihre Xpath-Auswertung drückt aus, dass Sie nur nach Kind und niedriger suchen. Sie müssen zusätzliche Ausdrücke für die anderen Felder machen, d. H. Statistiken und Eigenschaften wie ich nehme an, dass Sie auch dort aufteilen wollen.