В продолжение предыдущих статей про SolidWorks...
P.S.: В предыдущих статьях я описывал как
можно просмотреть иерархию файла и пытался извлечь дерево материалов изделия.
Для получения дерева материалов я использовал неверный подход.
Задача:
прочитать фаил сохранений SolidWorks и получить информацию с описанием изделия
и деревом материалов.
Для реализации я использую
- Java 1.7
- Apache POI 3.8
- dom4j
Данный пост я разобью на 3 шага:
- Чтение файла, поиск доступных данных
- Получение необходимых данных
- Получение дерева материалов в формате XML
Шаг 1. Чтение файла, поиск доступных данных
Для чтение файла я использую такой код
FileInputStream fis = new FileInputStream(new File(path));В результате чего я получаю Root каталог внутренней структуры файла, как правило это объект DirectoryNode. В нутрии фаил содержит иерархию в которой хранится информация по изделию
POIFSFileSystem poifsFileSystem = new POIFSFileSystem(fis);
fis.close();
return poifsFileSystem.getRoot();
Дерево в внутри файла состоит из DirectoryNode и DocumentNode объектов.
После получения корневого элемента, нам необходимо просмотреть иерархую, дабы узнать где искать необходимою информацию. Прочитать иерархию можно с помощью данного кода:
public void readNodeAndWriteToConsoleContains(DirectoryNode node) {
Iteratoriterator = node.getEntries();
readIterator(iterator);
}
private void readIterator(Iteratoriterator) {
while (iterator.hasNext()) {
readNode(iterator.next());
}
}
private void readNode(Entry node) {
if (node.isDocumentEntry()) {
System.out.println(" == Directory name: " + node.getParent().getName() + " -- Document: " + node.getName());
}
if (node.isDirectoryEntry()) {
System.out.println("");
System.out.println(" == Directory name: " + node.getName());
readIterator(((DirectoryNode) node).getEntries());
System.out.println("");
}
}
В результате работы кода мы получим что то подобное:
== Directory name: Root Entry -- Document: Config-0-PropertiesКак правило вся вспомогательная информация по изделию размещается в DocumentSummaryInformation и SummaryInformation.
== Directory name: Root Entry -- Document: ISolidWorksInformation
== Directory name: Root Entry -- Document: DocumentSummaryInformation
== Directory name: swXmlContents
== Directory name: swXmlContents -- Document: MATERIALTREE
== Directory name: swXmlContents -- Document: KeyWords__ZLB
== Directory name: swXmlContents -- Document: Tables__ZLB
Шаг 2. Получение необходимых данных
Для начала нам необходимо получить основную информацию, в моем случае это:
- Наименование;
- Обозначение;
- Инвентарный номер документа.
Поля подобные SummaryInformation в нутрии себя хранят лист PropertySet в котором есть вся необходимая информация.
PropertySet summaryInformation = readDocumentNode.read(poifsFileSystem, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
в нутрии метод read выглядит так:
public PropertySet read(POIFSFileSystem poifsFileSystem, String nameDocument) throws IOException {
PropertySet ps = null;
DocumentInputStream dis = poifsFileSystem.createDocumentInputStream(nameDocument);
try {
ps = new PropertySet(dis);
} catch (NoPropertySetStreamException e) {
e.printStackTrace();
} catch (MarkUnsupportedException e) {
e.printStackTrace();
} finally {
dis.close();
}
return ps;
}
читаем PropertySet:
public Listread(PropertySet propertySet, String docName) {
Listresult = new ArrayList ();
PropertyEntry propertyEntry;
for (Section section : propertySet.getSections()) {
Mapobjects = section.getDictionary();
Property[] properties = section.getProperties();
Property property;
for (int i = 0; i < objects.size(); i++) {
property = properties[i];
propertyEntry = new PropertyEntry();
propertyEntry.setKey(objects.get(property.getID()));
propertyEntry.setValue(property.getValue().toString());
propertyEntry.setIndex(i);
propertyEntry.setType(property.getType());
propertyEntry.setDocumentName(docName);
result.add(propertyEntry);
}
}
return result;
}
в результате чего получаем примерно следующие:
DocumentSummaryInformation / Наименование / Какойто чертеж
DocumentSummaryInformation / Обозначение / 87514567
DocumentSummaryInformation / Инвентарный номер документа / 221673
DocumentSummaryInformation / Формат / А4
... прочие данные ...
Шаг 3. Получение дерева материалов в формате XML
Замечательно, мы получили все нужные нам данные, теперь для полноты данных, необходимо получить дерево материалов из которых состоит изделие. Для этого мне надо в Директории файла swXmlContents, прочитать документ MATERIALTREE, данные в котором лежат в формате xml. Задачка простая, делаю это с помощью данного кода:
получаю корневой элемент дерева и перехожу в swXmlContents:
DirectoryNode swXmlContentsDir = (DirectoryNode) poifsFileSystem.getRoot().getEntry("swXmlContents");
после чего читаю документ MATERIALTREE:
DocumentInputStream dis = readDocumentNode.getDocumentInputStream(swXmlContentsDir, "MATERIALTREE");
SAXReader reader = new SAXReader();getDocumentInputStream возвращает имплементацию InputStream из которой я могу прочитать поток данных, в моем случаем это данные в формате XML который я сразу читаю dom4j.
Document document = reader.read(dis);
Заключение:
Спасибо за помощь Streamdown, пост в блоге "Необычная работа с документами solidworks".
Документация и примеры по работе с Apache POI