Sorry. Das File ist so groß. Das zu anonymisieren, dauert ne ganze Weile.
Ich habe mir noch einen Agenten im Domino Directory geschrieben, der Dokumente aus dem Domino Directory exportiert.
Option Public
Option Declare
' ### constants ###
Private Const BIF_DONTGOBELOWDOMAIN = &H2
Private Const BIF_RETURNONLYFSDIRS = &H1
Private Const DLG_FOLDER_TITLE = "Wählen Sie eine Ordner"
Private Const MAX_PATH = 260
' ### user defined types ###
' BrowseInfo
Private Type BrowseInfo
hOwner As Long
pidlRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type
' ### external functions ###
Declare Private Function apiGetActiveWindow Lib "user32" Alias "GetActiveWindow" () As Long ' Retrieves the active window.
Declare Private Function apiSHBrowseForFolder Lib "shell32.dll" Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long ' This function displays a dialog box that allows a user to select a folder.
Declare Private Function apiSHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" (Byval pidl As Long, Byval pszPath As String) As Long ' This function converts an item identifier list to a file system path.
Sub Initialize
Dim db As NotesDatabase
Dim dc As NotesDocumentCollection
Dim doc As NotesDocument
Dim lng_counter As Long
Dim nde As NotesDXLExporter
Dim ns As NotesStream
Dim s As NotesSession
Dim str_filepath As String
Dim str_path As String
Dim uiws As NotesUIWorkspace
' ### initialize ###
Set s = New NotesSession
Set db = s.CurrentDatabase
' ### get the current or all selected documents ###
Set dc = db.UnprocessedDocuments
If dc.Count = 0 Then
Print "No document selected!"
Goto terminate
End If
' ### choose the target directory ###
str_path = DlgFolder
If str_path = "" Then Goto terminate
' ### create dxl exporter ###
Set nde = s.CreateDXLExporter
' ### run through all documents ###
Set doc = dc.GetFirstDocument
Do Until doc Is Nothing
' build the target filename
str_filepath = str_path & "\" & doc.NoteID & ".dxl"
' open or create target file
Set ns = s.CreateStream
If ns.Open(str_filepath) = False Then
Print "Could not open or create file " & str_filepath
Goto nextdoc
End If
Call ns.Truncate
' set input and output for dxl exporter
Call nde.SetInput(doc)
Call nde.SetOutput(ns)
' export dxl
Call nde.Process
' close target file
Call ns.Close
nextdoc:
lng_counter = lng_counter + 1
Print lng_counter & " of " & dc.Count & " document(s) exported"
Set doc = dc.GetNextDocument(doc)
Loop
' ### terminate ###
terminate:
Set doc = Nothing
Set dc = Nothing
Set db = Nothing
Set s = Nothing
End Sub
Function DlgFolder As String
' Opens a Treeview control that displays the directories in a computer
Dim lng_lpidl As Long
Dim str_buffer As String
Dim bi As BrowseInfo
' ### dialog ###
' set dialog properties
bi.hOwner = apiGetActiveWindow
bi.lpszTitle = DLG_FOLDER_TITLE
bi.ulFlags = BIF_RETURNONLYFSDIRS + BIF_DONTGOBELOWDOMAIN
' show dialog
lng_lpidl = apiSHBrowseForFolder(bi)
' translate id list
If (lng_lpidl) Then
str_buffer = Space(MAX_PATH)
Call apiSHGetPathFromIDList(lng_lpidl, str_buffer)
str_buffer = Left(str_buffer, Instr(str_buffer, Chr(0)) - 1)
DlgFolder = str_buffer
End If
' ### terminate ###
terminate:
End Function
Der Agent sollte auf ausgewählte Dokumente laufen.
Der einzigste Unterschied gegen über den Files im IBM_TECHINCAL_SUPPORT-Verzeichnis ist:
Agent:
<!DOCTYPE document SYSTEM 'xmlschemas/domino_7_0_2.dtd'>
<document xmlns='http://www.lotus.com/dxl' version='7.0' maintenanceversion='2.0'
replicaid='C1256AEE00321D4B' form='Server'>
IBM_TECHINCAL_SUPPORT:
<!DOCTYPE note SYSTEM 'domino_6_5_5.dtd'>
<note class='document' xmlns='http://www.lotus.com/dxl' version='6.5' maintenanceversion='5.0' replicaid='C12570B3004DFDF2'>
Du wärest ein Gott.
Mit Religion hat das nix zu tun. Es ist nur ein bischen Arbeit. Trainier halt manchmal ein wenig. Kann das auch öffentlich tun. Angesichts meiner Tagessätze rechnet sich das sowieso.
OK.
Das ist jetzt eine Art proof of concept. Es kann einiges verbessert werden.
Der Agent holt sich zur Zeit eine Datei C:/dxl/hello.xml
Eigentlich müßte er über ein Verzeichnis iterieren und die einzelnen dxl-Dateien da rausholen.
Nicht so schwierig, das zu programmieren.
Der Agent holt sich zur Zeit eine Datei C:/dxl/hello.xsl
Besser wäre es, wenn das xsl in einem Konfig-Dokument gespeichert wäre. Auch das sollte nicht so schwierig zu programmieren sein.
Der Agent schreibt eine Datei C:/dxl/hello.html
Sowohl beim generierten html (ist im .xsl) als auch im Aufbau der xsl selbst, kann noch eine Menge verbessert werden.
Die Errormeldungen des aus der Hilfe kopierten Agenten sind nicht so das Gelbe. Da müßte noch geguckt werden, inwieweit da insbesondere xsl-Fehler besser ausgegeben werden können. Das warn bischen nervig. Hab kein Tool benutzt (hätte Sinn gemacht) sondern rein Notes.
Ich denke die Streams sollten besser mit einem close geschlossen werden.
Der Agent:
Options:
Option Public
Option Declare
%INCLUDE "lsxbeerr.lss"
Initialize:
Sub Initialize
On Error lsERR_NOTES_XSLT_INPUT_OBJECT Goto err_IN
On Error lsERR_NOTES_XSLT_OUTPUT_OBJECT Goto err_OUT
On Error lsERR_NOTES_XSLT_STYLESHEET_OBJECT Goto err_SS
Dim session As New NotesSession
Dim filename As String
Dim pathname As String
filename$ = "hello"
pathname$ = "c:\dxl\"
Dim XML_in As NotesStream ' input file
Set XML_in=session.CreateStream
If Not XML_in.Open(pathname$ & filename$ & ".xml") Then
Messagebox "Cannot open " & filename$,, "XML file error"
Exit Sub
End If
If XML_in.Bytes = 0 Then
Messagebox filename$ & " does not exist or is empty",, "XML file error"
Exit Sub
End If
Dim XSL_ss As NotesStream ' style sheet
Set XSL_ss=session.CreateStream
If Not XSL_ss.Open(pathname$ & filename$ & ".xsl") Then
Messagebox "Cannot open " & filename$,, "XSL file error"
Exit Sub
End If
Dim XML_out As NotesStream ' output file
Set XML_out=session.CreateStream
If Not XML_out.Open(pathname$ & filename$ & ".html") Then
Messagebox "Cannot create " & filename$,, "HTML file error"
Exit Sub
End If
XML_out.Truncate
Dim transformer As NotesXSLTransformer
Set transformer=session.CreateXSLTransformer(XML_in, XSL_ss, XML_out)
transformer.Process
Exit Sub
err_IN:
Messagebox "XSL Input error", , "XSLTransformer Process"
Exit Sub
err_OUT:
Messagebox "XSL Output error", , "XSLTransformer Process"
Exit Sub
err_SS:
Messagebox "Style Sheet error", , "XSLTransformer Process"
Exit Sub
End Sub
xsl [OBSOLET, bessere Version s.u.)]
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:d="http://www.lotus.com/dxl">
<xsl:output method="html"/>
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY>
<table>
<xsl:apply-templates/>
</table>
</BODY>
</HTML>
</xsl:template>
<xsl:template match="/d:document">
<xsl:for-each select="@*">
<tr>
<td>
document metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/d:document">
<xsl:for-each select="@*">
<tr>
<td>
document metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/d:document/d:noteinfo">
<xsl:for-each select="@*">
<tr>
<td>
noteinfo metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/d:document/d:noteinfo/d:created/d:datetime">
<xsl:for-each select="@*">
<tr>
<td>
noteinfo created metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<tr>
<td>
noteinfo created metadata value
</td>
<td>
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:noteinfo/d:modified/d:datetime">
<xsl:for-each select="@*">
<tr>
<td>
noteinfo modified metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<tr>
<td>
noteinfo modified metadata value
</td>
<td>
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:noteinfo/d:revised/d:datetime">
<xsl:for-each select="@*">
<tr>
<td>
noteinfo revised metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<tr>
<td>
noteinfo revised metadata value
</td>
<td>
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:noteinfo/d:lastaccessed/d:datetime">
<xsl:for-each select="@*">
<tr>
<td>
noteinfo lastaccessed metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<tr>
<td>
noteinfo lastaccessed metadata value
</td>
<td>
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:noteinfo/d:addedtofile/d:datetime">
<xsl:for-each select="@*">
<tr>
<td>
noteinfo addedtofile metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<tr>
<td>
noteinfo addedtofile metadata value
</td>
<td>
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:updatedby/d:name">
<xsl:for-each select="@*">
<tr>
<td>
updatedby metadata
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<tr>
<td>
updatedby metadata value
</td>
<td>
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="d:document/d:item">
<tr>
<td class="key">
<xsl:value-of select="@name"/>
</td>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:item/d:text">
<td class="value">
<xsl:value-of select="text()"/>
</td>
</xsl:template>
<xsl:template match="/d:document/d:item/d:text">
<td class="text-value">
<xsl:value-of select="text()"/>
</td>
</xsl:template>
<xsl:template match="/d:document/d:item/d:textlist/d:text">
<td class="multi-text-value">
<xsl:value-of select="text()"/>
</td>
</xsl:template>
<xsl:template match="/d:document/d:item/d:number">
<td class="number-value">
<xsl:value-of select="text()"/>
</td>
</xsl:template>
<xsl:template match="/d:document/d:item/d:datetime">
<td class="text-value">
<xsl:value-of select="text()"/>
</td>
</xsl:template>
<xsl:template match="/d:document/d:item/d:datetimelist/d:datetimepair/d:datetime">
<td class="date-time-list">
<xsl:value-of select="text()"/>
</td>
</xsl:template>
<xsl:template match="/d:document/d:item/d:rawitemdata">
<td class="raw-item-value">
type:<xsl:value-of select="@type"/>
</td>
<td class="raw-item-value">
<xsl:value-of select="text()"/>
</td>
</xsl:template>
<!--
<document xmlns='http://www.lotus.com/dxl' version='7.0' maintenanceversion='2.0'
replicaid='C1257566003E4722' form='Server'>
<noteinfo noteid='1476' unid='E2B84EF46C02A370C12575930045E264' sequence='1'>
<created><datetime dst='true'>20090409T144319,40+02</datetime></created>
<modified><datetime dst='true'>20090409T144702,93+02</datetime></modified>
<revised><datetime dst='true'>20090409T144702,92+02</datetime></revised>
<lastaccessed><datetime dst='true'>20090409T144702,93+02</datetime></lastaccessed>
<addedtofile><datetime dst='true'>20090409T144702,93+02</datetime></addedtofile></noteinfo>
<updatedby><name>CN=Test User/O=Test</name></updatedby>
-->
</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:d="http://www.lotus.com/dxl">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:output doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"/>
<xsl:output doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<table border="1"><xsl:apply-templates mode="meta"/></table>
<br/><br/>
<table border="1">
<xsl:apply-templates mode="item"/>
</table>
</body>
</html>
</xsl:template>
<!-- MODE META start -->
<xsl:template match="/d:document" mode="meta">
<xsl:for-each select="@*">
<tr>
<td>
document <xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<xsl:apply-templates mode="meta"/>
</xsl:template>
<xsl:template match="/d:document/d:item" mode="meta"/>
<xsl:template match="/d:document/d:noteinfo" mode="meta">
<xsl:for-each select="@*">
<tr>
<td>
noteinfo <xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
<xsl:apply-templates mode="meta"/>
</xsl:template>
<xsl:template match="/d:document/d:noteinfo/d:created|d:modified|d:revised|d:lastaccessed|d:addedtofile" mode="meta">
<tr>
<td>
<xsl:value-of select="name()"/>
</td>
<td>
<xsl:value-of select="./d:datetime/text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:updatedby/d:name" mode="meta">
<tr>
<td>
updatedby
</td>
<td>
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<!-- MODE META end -->
<!-- MODE ITEM start -->
<xsl:template match="/d:document/d:noteinfo" mode="item"/>
<xsl:template match="/d:document/d:updatedby" mode="item"/>
<xsl:template match="/d:document/d:item" mode="item">
<xsl:apply-templates mode="item">
<xsl:with-param name="name" select="@name"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="/d:document/d:item/d:text" mode="item">
<xsl:param name="name"/>
<xsl:if test="string-length(normalize-space(text())) > 0">
<tr>
<td class="key">
<xsl:value-of select="$name"/>
</td>
<td class="value">
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:if>
</xsl:template>
<xsl:template match="/d:document/d:item/d:textlist" mode="item">
<xsl:param name="name"/>
<tr>
<td class="key">
<xsl:value-of select="$name"/>
</td>
<td class="value">
<xsl:apply-templates mode="item"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:item/d:textlist/d:text" mode="item">
<xsl:if test="position() > 1">, </xsl:if><xsl:value-of select="text()"/>
</xsl:template>
<xsl:template match="/d:document/d:item/d:number" mode="item">
<xsl:param name="name"/>
<tr>
<td class="key">
<xsl:value-of select="$name"/>
</td>
<td class="value">
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:item/d:datetime" mode="item">
<xsl:param name="name"/>
<tr>
<td class="key">
<xsl:value-of select="$name"/>
</td>
<td class="value">
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:item/d:datetimelist/d:datetimepair" mode="item">
<xsl:param name="name"/>
<tr>
<td class="key">
<xsl:value-of select="$name"/>
</td>
<td class="value">
<xsl:apply-templates mode="item"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/d:document/d:item/d:datetimelist/d:datetimepair/d:datetime" mode="item">
<xsl:if test="position() > 1"> - </xsl:if><xsl:value-of select="text()"/>
</xsl:template>
<xsl:template match="/d:document/d:item/d:rawitemdata" mode="item">
<xsl:param name="name"/>
<tr>
<td class="key">
<xsl:value-of select="$name"/>
</td>
<td class="value">
<xsl:value-of select="text()"/>
</td>
</tr></xsl:template>
<!-- MODE ITEM end -->
</xsl:stylesheet>
Dieses xslt ist kompakter und zeigt nun keine Felder mehr an, die keine Werte haben.
Die Darstellung ist ein wenig übersichtlicher.
Probleme macht noch der exzessiv generierte whitespace und ein paar andere Dinge.
Mit der Formatierung ist es halt eine Frage wie du das html schreibst.
Genauso wie das Dokument in Notes dürfte aber schwierig sein, da im dxl die items unsortiert sind.
Meine zusätzlichen Features sind:
- leere Textfelder werden gar nicht angezeigt:
<xsl:template match="/d:document/d:item/d:text" mode="item">
<xsl:param name="name"/>
<xsl:if test="string-length(normalize-space(text())) > 0">
<tr>
<td class="key">
<xsl:value-of select="$name"/>
</td>
<td class="value">
<xsl:value-of select="text()"/>
</td>
</tr>
</xsl:if>
</xsl:template>
Mehrfachwertefelder werden bei Textfeldern mit Komma getrennt:
<xsl:template match="/d:document/d:item/d:textlist/d:text" mode="item">
<xsl:if test="position() > 1">, </xsl:if><xsl:value-of select="text()"/>
</xsl:template>
Ansonsten gefallen mir auch manche Sachen besser bei deinem code. Wenn ich morgen Zeit hab, mach ich einen merge. Bin auch nicht der Weltmeister in xslt. Will aber jetzt besser werden.