Форум visio.getbb.ru |
О форумах
Библиотека | Частые вопросы | Литература | Склад материалов Полезные ссылки | О сайте История Visio | Продукты Visio |
Для русскоязычных пользователей Visio. Начинающих и профессионалов. Где взять, как сделать, что купить и т.д. |
Выборка данных из файла Visio по XML технологииГеннадий Туманов Так как Visio, начиная с 2002 версии позволяет сохранять документ в формате XML (.vdx) интересно было попробовать использовать его в качестве XML источника данных. Попробовал, вот что получилось. Исходный файл d1.vdx содержит всего три прямоугольника с Custom Properties p1, p2 и p3. Ставилась задача – выбрать эти Custom Properties. Вспомогательный инструмент – MSXML. Программа написана в VB6. Проверены два способа: работа с DOM и XSLT-преобразование. Работа с DOMРабота с DOM никаких неожиданностей не принесла. Вот такой текст Sub GetCustProp() 'Выборка данных из Visio файла с помощью MSXML Dim xmlVis As MSXML2.DOMDocument 'Исходный документ Dim NL As MSXML2.IXMLDOMNodeList Dim NL1 As MSXML2.IXMLDOMNodeList Dim NL2 As MSXML2.IXMLDOMNodeList Set xmlVis = New MSXML2.DOMDocument xmlVis.validateOnParse = False xmlVis.async = False s = fPath & "d1.vdx"../p> xmlVis.Load (s) Set NL = xmlVis.getElementsByTagName("../Shape") For i = 0 To NL.length - 1 Set NL1 = NL.Item(i).selectNodes("@ID") Debug.Print "ID шейпа = " & NL1.Item(0).Text Set NL1 = NL.Item(i).selectNodes("Prop") s = ""../p> For j = 0 To NL1.length - 1 Set NL2 = NL1.Item(j).selectNodes("Label") s = s & NL2.Item(0).Text Set NL2 = NL1.Item(j).selectNodes("Value") s = s & " = " & NL2.Item(0).Text & "; "../p> Next Debug.Print s Next Set xmlVis = Nothing End Sub дает вот такой вывод ID шейпа = 1 p1 = Первый; p2 = wetwer; p3 = fgdfgsdfgsdf; ID шейпа = 2 p1 = Второй; p2 = wert wer wer ; p3 = gh fg hfgh fg h; ID шейпа = 3 p1 = Третий; p2 = kkkkkk; p3 = uyyyyyyyyi iiii; Все, что требуется, – ориентироваться в XML модели Visio. Работа с XSLT-преобразованиемЭтот вариант дался немного потяжелее. Текст программы Sub CopyCustPropToFile() 'Конвертирование Visio файла с помощью MSXML. XLT-преобразование Dim xmlSource As MSXML2.DOMDocument Dim xmlTr As MSXML2.DOMDocument Set xmlSource = New MSXML2.DOMDocument xmlSource.validateOnParse = False xmlSource.async = False s = fPath & "d1.vdx"../p> 'Из входного файла приходится вырезать xmlns s1 = fPath & "d1.vdx"../p> s2 = fPath & "temp.vdx"../p> Open s1 For Input As #1 Open s2 For Output As #2 Input #1, s3 Print #2, s3 Input #1, s3 s3 = Replace(s3, " xmlns='http://schemas.microsoft.com/visio/2003/core'", "") Print #2, s3 Do While Not EOF(1) Input #1, s3 Print #2, s3 Loop Close #1 Close #2 'На вход загружается почищенная копия s = fPath & "temp.vdx"../p> xmlSource.Load (s) 'Загрузка трансформатора Set xmlTr = New MSXML2.DOMDocument xmlTr.validateOnParse = False s = fPath & "Автоконвертор.xslt"../p> xmlTr.Load (s) 'Вот собственно преобразование s = xmlSource.transformNode(xmlTr) 'Трансформатор по умолчанию создает выходной файл в кодировке "UTF-16"../p> 'Это можно исправить непосредственно в трансформаторе или (грубо) вручную функцией Replace s = Replace(s, "UTF-16", "Windows-1251") s1 = fPath & "d2.htm"../p> Open s1 For Output As #1 Print #1, s Close #1 Set xmlSource = Nothing Set xmlTr = Nothing End Sub Текст конвертора (файл Автоконвертор.xslt) <?xml version="1.0" encoding="ISO-8859-5"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"../p> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <xsl:template match="/"> <html> <head /> <body> <xsl:for-each select="VisioDocument"> <xsl:for-each select="DocumentSheet"> <xsl:for-each select="@NameU"> <xsl:value-of select="."../> </xsl:for-each> </xsl:for-each> <br /> <xsl:for-each select="Pages/Page"> <xsl:for-each select="@NameU">Страница = <xsl:value-of select="."../> </xsl:for-each> <br /> <table border="1"> <xsl:for-each select="Shapes"> <xsl:for-each select="Shape"> <tr> <xsl:for-each select="Prop"> <td> <xsl:for-each select="Label"> <xsl:value-of select="."../> </xsl:for-each> = <xsl:for-each select="Value"> <xsl:value-of select="."../> </xsl:for-each> </td> </xsl:for-each> </tr> </xsl:for-each> </xsl:for-each> </table> </xsl:for-each> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet> На выходе получается html файл d2.htm примерно такого вида TheDoc Страница = Page-1 p1 = Первый p2 = wetwer p3 = fgdfgsdfgsdf p1 = Второй p2 = wert wer wer p3 = gh fg hfgh fg h p1 = Третий p2 = kkkkkk p3 = uyyyyyyyyi iiii Все неприятности возникли почему-то из-за ссылки на пространство имен. Visio вставляет в файл атрибут xmlns='http://schemas.microsoft.com/visio/2003/core'. Но MSXML с такой ссылкой работать отказывается (еще надо бы выяснить, почему). Удаляться через RemoveNamedItem такой атрибут отказывается (другие атрибуты удаляются). Причина скорее всего в том, что привязка к пространству имен в MSXML очень глубокая. Однажды захватив эту ссылку, он уже распространяет ее на весь документ. При попытке удаления атрибута со ссылкой атрибут на самом деле удаляется, но для сохранения привязки MSXML тут же вставляет аналогичный атрибут в другом месте. Аналогичная история происходит при попытке создать новый документ и поэлементно перенести в него компоненты из первого. Ссылка xmlns размножается и присваивается каждому переносимому компоненту. Радикальный способ – удалить ссылку непосредственно во входном файле. Это работает. Если весь входной файл переписать во временный, вычистив из второй строки ссылку xmlns, и подать полученную копию на вход конвертора, у MSXML претензий не возникает. Так и сделано в приведенном примере. |