From 2cf5a977aa470f560a052df3b0acc263bd0e3b52 Mon Sep 17 00:00:00 2001 From: Javen O'Neal Date: Wed, 25 Oct 2017 18:19:12 +0000 Subject: [PATCH] bug 61630: further XSSFExportToXML performance improvements from Daniel (bug 61630 comment 15, attachment 35450) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1813332 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xssf/extractor/XSSFExportToXml.java | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java index 9b20af4a1..140de7215 100644 --- a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java +++ b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java @@ -82,7 +82,7 @@ public class XSSFExportToXml implements Comparator{ private static final POILogger LOG = POILogFactory.getLogger(XSSFExportToXml.class); private XSSFMap map; - + private final HashMap indexMap = new HashMap<>(); /** * Creates a new exporter and sets the mapping to be used when generating the XML output document * @@ -146,8 +146,10 @@ public class XSSFExportToXml implements Comparator{ tableMappings.put(commonXPath, table); } + indexMap.clear(); xpaths.sort(this); - + indexMap.clear(); + for(String xpath : xpaths) { XSSFSingleXmlCell simpleXmlCell = singleXmlCellsMappings.get(xpath); @@ -401,6 +403,7 @@ public class XSSFExportToXml implements Comparator{ String[] leftTokens = leftXpath.split("/"); String[] rightTokens = rightXpath.split("/"); + String samePath = ""; int minLength = leftTokens.length< rightTokens.length? leftTokens.length : rightTokens.length; @@ -412,47 +415,52 @@ public class XSSFExportToXml implements Comparator{ String rightElementName = rightTokens[i]; if (leftElementName.equals(rightElementName)) { + samePath += "/" + leftElementName; localComplexTypeRootNode = getComplexTypeForElement(leftElementName, xmlSchema, localComplexTypeRootNode); } else { - int leftIndex = indexOfElementInComplexType(leftElementName,localComplexTypeRootNode); - int rightIndex = indexOfElementInComplexType(rightElementName,localComplexTypeRootNode); - if (leftIndex!=-1 && rightIndex!=-1) { - if ( leftIndex < rightIndex) { - return -1; - }if ( leftIndex > rightIndex) { - return 1; - } - } /*else { - // NOTE: the xpath doesn't match correctly in the schema - }*/ + return indexOfElementInComplexType(samePath, leftElementName, rightElementName,localComplexTypeRootNode); } } return 0; } - private int indexOfElementInComplexType(String elementName,Node complexType) { + private int indexOfElementInComplexType(String samePath,String leftElementName,String rightElementName,Node complexType) { if(complexType == null) { - return -1; + return 0; } - int indexOf = -1; int i = 0; Node node = complexType.getFirstChild(); - final String elementNameWithoutNamespace = removeNamespace(elementName); + final String leftWithoutNamespace = removeNamespace(leftElementName); + int leftIndexOf = getAndStoreIndex(samePath, leftWithoutNamespace); + final String rightWithoutNamespace = removeNamespace(rightElementName); + int rightIndexOf = getAndStoreIndex(samePath, rightWithoutNamespace); - while (node != null) { + while (node != null && (rightIndexOf==-1||leftIndexOf==-1)) { if (node instanceof Element && "element".equals(node.getLocalName())) { - Node element = getNameOrRefElement(node); - if (element.getNodeValue().equals(elementNameWithoutNamespace)) { - indexOf = i; - break; + String elementValue = getNameOrRefElement(node).getNodeValue(); + if (elementValue.equals(leftWithoutNamespace)) { + leftIndexOf = i; + indexMap.put(samePath+"/"+leftWithoutNamespace, leftIndexOf); + } + if (elementValue.equals(rightWithoutNamespace)) { + rightIndexOf = i; + indexMap.put(samePath+"/"+rightWithoutNamespace, leftIndexOf); } } i++; node = node.getNextSibling(); } - return indexOf; + if(leftIndexOf == -1 || rightIndexOf == -1) { + return 0; + } + return Integer.compare(leftIndexOf, rightIndexOf); + } + + private int getAndStoreIndex(String samePath,String withoutNamespace) { + String withPath = samePath+"/"+withoutNamespace; + return indexMap.getOrDefault(withPath, -1); } private Node getNameOrRefElement(Node node) {