07.17.11
Working with large XML files
- Figuring out the most helpful way of presenting the register data (more on that in another entry).
- Dealing with the sheer size of the register data files.
XML, e-bikes, and other stuff
<xsl:template match="/"> <root> <xsl:call-template name="rackem"/> </root> </xsl:template> <xsl:template name="rackem"> <xsl:variable name="setsize">500</xsl:variable> <xsl:variable name="x" select="//testnode"></xsl:variable> <xsl:for-each select="$x[(position() mod $setsize) = 1]"> <xsl:variable name="postion" select="position()"></xsl:variable> <set> <xsl:variable name="p" select="position()"/> <xsl:call-template name="stackem"> <xsl:with-param name="set" select="$p" /> <xsl:with-param name="total" select="$setsize"></xsl:with-param> </xsl:call-template> </set> </xsl:for-each> </xsl:template> <xsl:template name="stackem"> <xsl:param name="set">0</xsl:param> <xsl:param name="total">0</xsl:param> <xsl:param name="count">1</xsl:param> <xsl:variable name="p" select="(($set - 1) * $total) + $count"></xsl:variable> <xsl:variable name="x" select="//node"></xsl:variable> <xsl:if test="$count < ($total + 1)"> <setitem> <xsl:value-of select="$x[$p]"></xsl:value-of> </setitem> <xsl:call-template name="stackem"> <xsl:with-param name="set" select="$set" /> <xsl:with-param name="count" select="$count + 1"></xsl:with-param> <xsl:with-param name="total" select="$total"></xsl:with-param> </xsl:call-template> </xsl:if> </xsl:template>
<xsl:template name="hyphenate-tableentries"> <xsl:param name="entry" select="''"/> <xsl:choose> <xsl:when test="$tableentry.hyphenate = ''"> <xsl:value-of select="$entry"/> </xsl:when> <xsl:when test="string-length($entry) > 1"> <xsl:variable name="char" select="substring($entry, 1, 1)"/> <xsl:value-of select="$char"/> <xsl:if test="contains($tableentry.hyphenate.chars, $char)"> <xsl:if test="not($char = '/' and substring($entry,2,1) = '/')"> <xsl:copy-of select="$tableentry.hyphenate"/> </xsl:if> </xsl:if> <xsl:call-template name="hyphenate-tableentries"> <xsl:with-param name="entry" select="substring($entry, 2)"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$entry"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:param name="tableentry.hyphenate.chars">_-;:</xsl:param> <xsl:param name="tableentry.hyphenate"></xsl:param> <xsl:template match="entry//text()"> <xsl:call-template name="hyphenate-tableentries"> <xsl:with-param name="entry" select="."/> </xsl:call-template> </xsl:template>
' Module: SVGExportModule
' A collection of functions to export and process SVG files
'
' Revision History
' Number Date Name Description
' 1.00 2009/07/24 TC Initial release.
'
' 1.10 2010/03/24 TC Updated to fix font-size issue,
' test special characters,
' automatically add command bar.
'
' 1.20 2010/03/25 TC Corrected the macro to load the CommandBar
' according to Visio's process:
' 1) Load macro to ThisDocument
' 2) Added an on document open macro using the property:
' "Document_DocumentOpened(ByVal doc As IVDocument)"
' 3) Added an on document close macro using the property
' "Document_BeforeDocumentClose(ByVal doc As IVDocument)"
' Added an optional argument to CommandBarAdd to exit
' after removing the toolbar.
'
' ' Contents
' Main function
' - SVGExport: Saves current file or selection as SVG,
' then opens file as text string in order
' to process search and replace operations
'
' File Common Dialog Library
' - GetSaveFileName (private function)
' - ShowSaveFileDialog
'
' CommandBar functions
' - See ThisDocument.Document_DocumentOpened(ByVal doc As IVDocument)
' - CommandBarAdd: adds CommandBar
' - CommandBarClear: removes CommandBar
'
' Utility functions
' - GetText: Open a text file to store into a string
' - OutputText: Write a string to a text file
' - ProcessText: search and replace character strings in text
' - SplitName: separates filename from its extension ''======================================================
'' Library: File Common Dialog Library
'' Desc: Compensates for Visio's lack of the
'' common MSO FileDialog
'' Call: ShowSaveFileDialog()
'' Arguments: sFilter--File name filter (required)
'' sDefExt--Default extension
'' sInitDir--Initial directory
'' lFlags--File flag combinations. See Common Dialogs Help
'' hParent--Handle of he parent form
'' Comments: FileName is same as the current file
'' Changes----------------------------------------------
'' Date Programmer Change
'' 20010421 Marco Belinaso http://www.devx.com/vb2themax/Tip/19260
''====================================================== Private Declare Function GetSaveFileName Lib "comdlg32.dll" Alias _
"GetSaveFileNameA" (pOpenfilename As OpenFilename) As Long Private Type OpenFilename
lStructSize As Long
hwndOwner As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
iFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type Private Enum OFNFlagsEnum
OFN_ALLOWMULTISELECT = &H200
OFN_CREATEPROMPT = &H2000
OFN_ENABLEHOOK = &H20
OFN_ENABLETEMPLATE = &H40
OFN_ENABLETEMPLATEHANDLE = &H80
OFN_EXPLORER = &H80000
OFN_EXTENSIONDIFFERENT = &H400
OFN_FILEMUSTEXIST = &H1000
OFN_HIDEREADONLY = &H4
OFN_LONGNAMES = &H200000
OFN_NOCHANGEDIR = &H8
OFN_NODEREFERENCELINKS = &H100000
OFN_NOLONGNAMES = &H40000
OFN_NONETWORKBUTTON = &H20000
OFN_NOREADONLYRETURN = &H8000
OFN_NOTESTFILECREATE = &H10000
OFN_NOVALIDATE = &H100
OFN_OVERWRITEPROMPT = &H2
OFN_PATHMUSTEXIST = &H800
OFN_READONLY = &H1
OFN_SHAREAWARE = &H4000
OFN_SHAREFALLTHROUGH = 2
OFN_SHARENOWARN = 1
OFN_SHAREWARN = 0
OFN_SHOWHELP = &H10
End Enum ' All functions must appear after Declare and Enum ' Show the common dialog to select a file to save. Returns the path of the
' selected file or a null string if the dialog is canceled ' Parameters: ' Example:
' Dim sFilter As String
' 'set the filter: show text files and all the files
' sFilter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"
' 'let the user select a file, an ask for confirmation if the file already
' exists
' MsgBox "File selected: " & ShowOpenFileDialog(sFilter, "txt",
' "C:\Documents", OFN_OVERWRITEPROMPT) Function ShowSaveFileDialog(Optional ByVal sFilter As String, Optional ByVal sDefExt As _
String, Optional ByVal sInitDir As String, Optional ByVal lFlags As Long, _
Optional ByVal hParent As Long) As String
Dim OFN As OpenFilename
On Error Resume Next
' set the values for the OpenFileName struct
With OFN
.lStructSize = Len(OFN)
.hwndOwner = hParent
.lpstrFilter = Replace(sFilter, "|", vbNullChar) & vbNullChar
.lpstrFile = Space$(255) & vbNullChar & vbNullChar
.nMaxFile = Len(.lpstrFile)
.flags = lFlags
.lpstrInitialDir = sInitDir
.lpstrDefExt = sDefExt
End With
' show the dialog
If GetSaveFileName(OFN) Then
' extract the selected file (including the path)
ShowSaveFileDialog = Left$(OFN.lpstrFile, InStr(OFN.lpstrFile, _
vbNullChar) - 1)
End If
End Function ''======================================================
'' Program: CommandBarAdd
'' Desc: Add CommandBar - MS Office 2003 only
'' Visio doesn't use the Ribbon UI
'' Call: CommandBarAdd
'' Arguments: None
'' Comments: Note: should Visio ever change capability
'' this function will need to change
'' Changes----------------------------------------------
'' Date Programmer Change
'' 20090724 Tony Chung Written
'' 20100326 Tony Chung Added the bRemove boolean
'' argument to immediately exit
'' after clearing toolbar
''======================================================
Sub CommandBarAdd(Optional bRemove As Boolean = False)
Dim cbrCmdBar As CommandBar, sCMdBarName As String
'' Create temporary toolbar that doesn't
'' persist between application sessions.
sCMdBarName = "SVGExport"
Call CommandBarClear(sCMdBarName) '' bRemove is set to True BeforeDocumentClose
'' this method ensures we close the same toolbar opened
'' by this macro (same variable name)
If bRemove = True Then GoTo CleanExit Set cbrCmdBar = Application.CommandBars.Add(Name:=sCMdBarName, Temporary:=True)
cbrCmdBar.Position = msoBarTop '' Add a button to MyDrawingCommandBar
'' that runs a VBA macro.
Set cbButton = cbrCmdBar.Controls.Add(Type:=msoControlButton)
With cbButton
.Caption = "Export SVG file"
.TooltipText = "Export SVG file that conforms to PMC schema"
.Style = msoButtonIconAndCaption
'' Use the Tag property for context switching and
'' for use with the FindControl method.
.Tag = "cbbVBAMacro"
'' Set the button face to use an internal icon.
.FaceID = 7075 '' Use the OnAction property to run a VBA macro
'' contained in this document.
.OnAction = "SVGExport"
End With
cbrCmdBar.Visible = True
CleanExit:
End Sub ''======================================================
'' Program: CommandBarClear
'' Desc: Remove specific CommandBar
'' Call: CommandBarClear(sName)
'' Arguments: sName--The CommandBar name to remove
'' Comments: Note: should Visio ever change capability
'' this function will need to change
'' Changes----------------------------------------------
'' Date Programmer Change
'' 20090724 Tony Chung Written
''======================================================
Private Sub CommandBarClear(sName As String)
'' Before adding a new CommandBar check for its
'' existence and remove itto avoid causing an error. Dim cmdBars As CommandBars
Set cmdBars = Application.CommandBars For i = 1 To cmdBars.Count
'' Debug.Print i & ": " & cmdBars(i).NameLocal
If cmdBars(i).NameLocal = sName Then
cmdBars(i).Delete
End If
Next i
End Sub ''======================================================
'' Program: SVGExport
'' Desc: Save as SVG, reopen to replace xmlns
'' and save as final SVG
'' Call: SVGExport()
'' Arguments: None.
'' Comments: FileName is same as the current file
'' Changes----------------------------------------------
'' Date Programmer Change
'' 20090724 Tony Chung Written
''====================================================== Sub SVGExport()
Dim sPath As String, sFileName As String, sFile As String
Dim sFName As String, sText As String, sRv As String '' establish page container
ActivePage.ResizeToFitContents
'' name file
sPath = ActiveDocument.Path
sFileName = SplitName(ActiveDocument.Name)
sFile = sPath & "\" & sFileName & ".svg"
'' hook into file dialog picker here
sFName = ShowSaveFileDialog( _
sFilter:="Scalable Vector Graphics (*.svg)", _
sDefExt:="svg", sInitDir:=sPath, _
lFlags:=OFN_OVERWRITEPROMPT) If Trim(sFName) = "" Then
MsgBox "Operation cancelled."
GoTo GracefulExit
End If sFile = sFName
'' export SVG
Application.ActiveWindow.Selection.Export sFile '' open file
sText = GetText(sFile)
'' process file
sText = ProcessText(sText)
'' write file
sRv = OutputText(sFile, sText)
If sRv = "Success" Then
MsgBox "File: " & sFile & " exported successfully"
Else
MsgBox "Error: " & sRv
End If
GracefulExit:
End Sub ''======================================================
'' Program: GetText
'' Desc: Read a text file into a string and then
'' return the string
'' Called by: ParseText
'' Call: GetText(sFile)
'' Arguments: sFile--The full path to the text file
'' Comments:
'' Changes----------------------------------------------
'' Date Programmer Change
'' 6/14/06 Charley Kyd Written
''======================================================
Function GetText(sFile As String) As String
Dim nSourceFile As Integer, sText As String ''Close any open text files
Close ''Get the number of the next free text file
nSourceFile = FreeFile ''Write the entire file to sText
Open sFile For Input As #nSourceFile
sText = Input$(LOF(1), 1)
Close #nSourceFile GetText = sText
End Function ''======================================================
'' Program: OutputText
'' Desc: Print the contents of a string into
'' a text file
'' Called by:
'' Call: OutputText(sFile, sText)
'' Arguments: sFile--The full path to the text file
'' sText--The text string to write
'' Comments:
'' Changes----------------------------------------------
'' Date Programmer Change
'' 6/14/06 Charley Kyd Written as GetText()
'' 7/24/09 Tony Chung Repurposed to OutputText()
'' Add basic error handling
''======================================================
Function OutputText(sFile As String, sText As String) As String
Dim nSourceFile As Integer, sRv As String '' Close any open text files
Close '' Get the number of the next free text file
nSourceFile = FreeFile '' Write the entire file to sText
On Error GoTo ErrHandler
Open sFile For Output As #nSourceFile
Print #nSourceFile, sText
Close #nSourceFile
GoTo CleanExit
ErrHandler:
sRv = Error CleanExit:
On Error GoTo 0
If sRv = "" Then sRv = "Success"
OutputText = sRv
End Function ''======================================================
'' Program: ProcessText
'' Desc: Add custom attributes to xml tags and
'' return the string
'' Called by:
'' Call: ProcessText(sText)
'' Arguments: sText--The xml string
'' Comments: Note: should Visio ever change capability
'' this function will need to change
'' Changes----------------------------------------------
'' Date Programmer Change
'' 20090724 Tony Chung Written
'' 20100324 Tony Chung Added handler to standardize
'' font-size between browsers
''====================================================== Function ProcessText(sText As String) As String
'' sRpl( lookup To replace, lookup value To replace value)
Dim sRpl(1 To 3, 1 To 2) As String
sRpl(1, 1) = "xmlns=""http://www.w3.org/2000/svg"""
sRpl(1, 2) = "xmlns=""http://www.w3.org/2000/svg"" xmlns:xlink=""http://www.w3.org/1999/xlink"""
sRpl(2, 1) = "<marker "
sRpl(2, 2) = "<marker overflow=""visible"" "
sRpl(3, 1) = "<![CDATA["
sRpl(3, 2) = "<![CDATA[" & vbCr & _
" svg {font-size:12px;}" & vbCr For i = LBound(sRpl) To UBound(sRpl)
sText = Replace(sText, sRpl(i, 1), sRpl(i, 2))
Next i ProcessText = sText
End Function ''======================================================
'' Program: SplitName
'' Desc: Utility function to remove extension
'' from filename
'' Call: SplitName(sFileName)
'' Arguments: sFileName--The string with filename.ext
'' Comments:
'' Changes----------------------------------------------
'' Date Programmer Change
'' 20090724 Tony Chung Written
''====================================================== Function SplitName(sFileName As String) As String
Dim lPosEnd As Long
Dim lPosStart As Long
'' Remove file extension
lPosEnd = InStrRev(sFileName, ".") - 1
If lPosEnd = 0 Then
lPosEnd = Len(sFileName) + 1
End If
SplitName = Mid$(sFileName, 1, lPosEnd)
End Function