rekursivt læs XML fil og byg todimensionelt array - feedback

Du kan i dette forum stille og svare på spørgsmål vedrørende Java programmering på alle typer platforme.
Besvar
cristian
Moderator
Moderator
Indlæg:882
Tilmeldt:26. sep 2011, 21:31
Kontakt:
rekursivt læs XML fil og byg todimensionelt array - feedback

Indlæg af cristian » 23. nov 2016, 11:23

Jeg har siddet og leget lidt med at læse en XML fil rekursivt og bygge et todimensionelt array.

Eksempel
Root element name: eveapi
namespace: []
date'\2016-11-05 15:08:16'\
refID'\13216563440'\
refTypeID'\1'\
ownerName1'\Benjamin Ambaek'\
ownerID1'\95654255'\
ownerName2'\Cristian Ambaek'\
ownerID2'\91472837'\
argName1'\Esa VIII - Moon 2 - Viziam Warehouse'\
argID1'\60006610'\
amount'\0.00'\
balance'\19691753.18'\
reason'\'\
taxReceiverID'\'\
taxAmount'\'\
owner1TypeID'\1385'\
owner2TypeID'\1377'\
Hvilket virker helt fint, mit spørgsmål er hvordan ville i eventuelt optimere følgende kode? Enten så den er mindre resource krævende, færre linjer / andet.

Kode: Vælg alt

/**
	 * @param list
	 *            XML document from getRootElement().getChildren().iterator()
	 * @param columnNames
	 *            column names from column="", can be null
	 * @param compactArray
	 *            array that will be used to build the output, can be null.
	 * @param arrayCount
	 *            place data in the correct columns after adding the column
	 *            name. Default start at 1.
	 */
	private static void diXmlRecursiveRead(Iterator<Element> list, String[] columnNames, String[][] compactArray,
			Integer arrayCount) {
		Element element = null;
		String[] columns = null;

		while (list.hasNext()) {
			element = list.next();

			// Assign data to the two dimensional array, starting from position
			// 1 in the length to not overwrite the column names.
			// This is also where i would print the column name plus its
			// attribute value if i was printing to console.
			if (columnNames != null) {
				for (int a = 0; a < columnNames.length; a++) {
					compactArray[a][arrayCount] = element.getAttributeValue(columnNames[a]);
				}
			}

			// Find the element that contains the columns="" information
			if (element.getAttributeValue("columns") != null) {
				// reset the array count, since we are processing a new
				// columns="" section
				arrayCount = 1;

				columns = element.getAttributeValue("columns").toString().split(",");

				// set width size +1 to make room for the column names
				// (columnNames + data +1)
				compactArray = new String[columns.length][element.getChildren().size() + 1];

				// Set the EVE column names in the first column of the two
				// dimensional array
				for (int a = 0; a < columns.length; a++) {
					compactArray[a][0] = columns[a];
				}
			}

			// After added the last value to the two dimensional array print the
			// array[][]
			if (compactArray != null) {
				if (arrayCount == (compactArray[0].length - 1)) {
					diPrintTwoDimensionalArrayCompact(compactArray);
				}
			}

			// Method calls itself with a new level of the child
			diXmlRecursiveRead(element.getChildren().iterator(), columns, compactArray, arrayCount++);
		}
	}

	private static void diPrintTwoDimensionalArrayCompact(String[][] dataArray) {
		StringBuilder sb = new StringBuilder();
		String newline = System.getProperty("line.separator");
		
		for (int a = 0; a < dataArray.length; a++) {
			for (int b = 0; b < dataArray[0].length; b++) {
				sb.append(dataArray[a][b] + "'\\");
			}
			sb.append(newline);
		}
		System.out.println(sb.toString());
	}
Tak på forhånd til alle som tager dig tid til at kigge på dette.

jepperask
Geni
Geni
Indlæg:378
Tilmeldt:4. nov 2012, 17:57

Re: rekursivt læs XML fil og byg todimensionelt array - feedback

Indlæg af jepperask » 27. nov 2016, 17:55

Har du eventuelt en hel klasse, inklusiv imports, så man kan køre det? :-)

cristian
Moderator
Moderator
Indlæg:882
Tilmeldt:26. sep 2011, 21:31
Kontakt:

Re: rekursivt læs XML fil og byg todimensionelt array - feedback

Indlæg af cristian » 28. nov 2016, 11:43

Siden jeg skrev denne tråd har metoden ændret sig en del da jeg ikke kunne få Java til at se at min if statement for hvornår jeg vil returner objekter altid ville blive opfyldt,
så Java kunne ikke vurdere om metoden nogensinde vil ende.

Kode: Vælg alt

return diPrintTwoDimensionalArrayCompact(compactArray);
i stedet for bare at printe indholdet ud.

Kode: Vælg alt

/**
	 * @param list
	 *            XML document from getRootElement().getChildren().iterator()
	 * @param columnNames
	 *            column names from column="", can be null
	 * @param compactArray
	 *            array that will be used to build the output, can be null.
	 * @param arrayCount
	 *            place data in the correct columns after adding the column
	 *            name. Default start at 1.
	 * @param returnArrayList
	 *            ArrayList to be returned with the 2d String[][] objects.
	 * 
	 */
	public void diXmlRecursiveRead(Iterator<Element> list, String[] columnNames, String[][] compactArray,
			Integer arrayCount, ArrayList<String[][]> returnArrayList) {

		// Declare an empty value we can use to reference with element objects
		// in the XML.
		Element element = null;

		while (list.hasNext()) {
			element = list.next();

			// Find the element that contains the columns="" information
			if (element.getAttributeValue("columns") != null) {
				// reset the array count, since we are processing a new
				// columns="" section
				arrayCount = 1;

				columnNames = element.getAttributeValue("columns").toString().split(",");

				// set width size +1 to make room for the column names
				// (columnNames + data +1)
				compactArray = new String[columnNames.length][element.getChildren().size() + 1];

				// Set the EVE column names in the first column of the two
				// dimensional array
				for (int a = 0; a < columnNames.length; a++) {
					compactArray[a][0] = columnNames[a];
				}
			}

			// Assign data to the two dimensional array, starting from position
			// 1 in the length to not overwrite the column names.
			// This is also where i would print the column name plus its
			// attribute value if i was printing to console.
			if (columnNames != null) {
				for (int a = 0; a < columnNames.length; a++) {
					compactArray[a][arrayCount] = element.getAttributeValue(columnNames[a]);
				}
			}

			// After added the last value to the two dimensional array, add it
			// to the arraylist, that later gets returned to the invoker so we can work with it.
			if (compactArray != null) {
				if (arrayCount == (compactArray[0].length - 1)) {
					returnArrayList.add(compactArray);
				}
			}

			// Method calls itself with a new level of the child
			diXmlRecursiveRead(element.getChildren().iterator(), columnNames, compactArray, arrayCount++,
					returnArrayList);
		}
	}
imports er rimelig lige til for metoden

import java.util.Iterator;
import org.jdom2.Element;

man skal dog fodre den med et iterator objekt når man kalder metoden

Kode: Vælg alt

document.getRootElement().getChildren().iterator()
Test XML
<eveapi version="2">
<currentTime>2016-11-16 10:38:03</currentTime>
<result>
<rowset name="transactions" key="refID" columns="date,refID,refTypeID,ownerName1,ownerID1,ownerName2,ownerID2,argName1,argID1,amount,balance,reason,taxReceiverID,taxAmount,owner1TypeID,owner2TypeID">
<row date="2016-11-05 15:08:16" refID="13216563440" refTypeID="1" ownerName1="Benjamin Ambaek" ownerID1="95654255" ownerName2="Cristian Ambaek" ownerID2="91472837" argName1="Esa VIII - Moon 2 - Viziam Warehouse" argID1="60006610" amount="0.00" balance="19691753.18" reason="" taxReceiverID="" taxAmount="" owner1TypeID="1385" owner2TypeID="1377"/>
<row date="2016-11-05 13:43:11" refID="13216280365" refTypeID="42" ownerName1="Cristian Ambaek" ownerID1="91472837" ownerName2="" ownerID2="0" argName1="" argID1="0" amount="-14791.98" balance="19691753.18" reason="" taxReceiverID="" taxAmount="" owner1TypeID="2" owner2TypeID="1377"/>
<row date="2016-11-05 13:42:58" refID="13216279642" refTypeID="42" ownerName1="Cristian Ambaek" ownerID1="91472837" ownerName2="" ownerID2="0" argName1="" argID1="0" amount="-1049987.86" balance="19706545.16" reason="" taxReceiverID="" taxAmount="" owner1TypeID="2" owner2TypeID="1377"/>
</rowset>
</result>
<cachedUntil>2016-11-16 11:05:03</cachedUntil>
</eveapi>
output eksempel hvis man tager print metoden i #0
columnname|value|value|value|
columnname|value|value|value|

Besvar