C#
Alles rund ums Thema C#
XSLT Transformation in C#
0Ich hatte ein recht umfangreiches Xml-Schema. Dieses wird ständig mal erweitert und eine andere Applikation benötigt nur einen Teil dieses Schemas. Dazu wurde es immer von Hand für die andere Applikation geändert. Um mir das Leben einfacher zu machen, wollte ich dies über eine XSLT-Transformation lösen, schließlich ist ein Schema auch nur eine XML-Datei. Ein großer Teil wurde einfach nur kopiert, dennoch sah die Ausgabe anders aus als die Eingabe. Mein Kopiertemplate sah folgendermaßen aus:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Einfach alle Nodes und Attribute kopieren, also nichts wildes. Dennoch wurde aus:
<xs:element name="comment" type="xs:string" minOccurs="0" />
folgendes:
<xs:element name="comment" type="xs:string" minOccurs="0"></xs:element>
Das Schema ist noch valide und funktioniert tadellos, nur sieht es nicht wirklich schön aus. Nachdem ich im Netz nach einen bestimmten Parameter im C#-Code und ähnliches gesucht hatte, wurde ich doch noch fündig. Das .NET-Framework bietet zwei verschiedene Methoden zur Transformation.
XslTransform und XslCompiledTransform. Der Kommentar in der MSDN sagt eigentlich alles:
Die XslCompiledTransform-Klasse ist ein XSLT-Prozessor, der die XSLT 1.0 Syntax unterstützt. Dies ist eine neue Implementierung, die im Vergleich zur veralteten XslTransform-Klasse die Leistung verbessert. Die Struktur der XslCompiledTransform-Klasse ist der XslTransform-Klasse sehr ähnlich.
Nebenbei werden auch noch das ShortEndTag unterstützt, womit mein Problem gelöst wäre. Der Vollständigkeit halber sollte noch auf diesen Blogeintrag hingewiesen werden: XslCompiledTransform Slower than XslTransform?, denn auch noch die veraltete XslTransform-Klasse scheint noch ihre Daseinsberechtigung zu haben.
Löschen von Nodes in einem XML-Dokument
1Ich hatte letztens ein XML-Dokument, welches ich etwas verschlanken wollte. Das Format war in etwa folgendes:
<root> <node1>Content</node1> <node2>Content</node2> <node3>Content</node3> <node4>Content</node4> </root>
Ich wollte nur die “node1″ – Node behalten, sprich alle anderen entfernen. Daher mein erster Ansatz:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml("<root><node1>Content</node1><node2>Content</node2><node3>Content</node3><node4>Content</node4></root>");
XPathNavigator navigator = xmlDocument.CreateNavigator();
string[] nodesToRemove = new[] {"//node2", "//node3", "//node4"};
foreach (var nodeName in nodesToRemove)
{
XPathNavigator node = navigator.SelectSingleNode(nodeName);
if (node != null)
{
node.DeleteSelf();
}
}
Console.WriteLine(xmlDocument.OuterXml);
Funktioniert und gut.
Nun wollte ich den Ansatz umdrehen, und alle Nodes entfernen, die nicht den Namen “node1″ haben.
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml("<root><node1>Content</node1><node2>Content</node2><node3>Content</node3><node4>Content</node4></root>");
XPathNavigator navigator = xmlDocument.CreateNavigator();
string xpath = "/root/node()[name()!='node1']";
XPathNodeIterator nodes = navigator.Select(xpath);
while(nodes.MoveNext())
{
if(nodes.Current != null)
{
nodes.Current.DeleteSelf();
}
}
Console.WriteLine(xmlDocument.OuterXml);
Leider war das Ergebnis nicht so wie erwartet, obwohl der XPath korrekt ist und die anderen Nodes selektiert. Es wurde nur “node2″ gelöscht, sprich die erste Node, welche mit dem NodeIterator angesprochen wird. Durch das DeleteSelf() liefert MoveNext() automatisch false zurück, wenn es wieder aufgerufen wird. Ähnliche Probleme gibt es etwa auch, wenn in einer foreach()-Schleife der Enumerator geändert wird. Eine mögliche Lösung wäre folgendes:
while(nodes.MoveNext())
{
if(nodes.Current != null)
{
nodes.Current.DeleteSelf();
nodes = navigator.Select(xpath);
}
}
Nach dem Löschen wird der XPath einfach noch mal ausgeführt. Meiner Meinung nach keine wirklich schöne Lösung, leider aber die einzige die ich gefunden habe, welche auch funktioniert.
HowTo: C# Programm nur mit NotifyIcon ohne Form starten
0Für den Fall, dass ihr eine Anwendung erstellen wollt, welche (zum Start) nur ein NotifyIcon (also ein Symbol in der Taskleiste besitzt), müsst ihr den Standardprogrammaufruf etwas abändern.
Der standardmäßig erstellte Code von VisualStudio startet automatisch eine Form. Diese könnte man nun ausblenden (WindowState = Minimized, ShowInTaskBar = false) aber es geht auch eleganter. Erstellt einfach ein NotifyIcon mit Icon und Visible = true und ruft Application.Run() ohne Parameter auf.
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
_trayIcon = new NotifyIcon {Icon = Icon.FromHandle(new Bitmap("Gear.png").GetHicon()), Visible = true};
_trayIcon.Click += TrayIconClick;
Application.Run();
_trayIcon.Dispose();
}
Im Anhang findet ihr eine Beispielsolution. Wichtig ist, dass ihr euch selbst ums Dispose() kümmern müsst, damit etwa das NotifyIcon aus der Taskleiste verschwindet, sobald die Applikation beendet wird. Das Beispiel öffnet beim Klick auf das NotifyIcon eine leere Form. Wird diese geschlossen, wird das ganze Programm beendet.
Passwort Karte
0Ich habe vor ein paar Tagen beim Hostblogger von der Passwort-Karte gelesen. Ich finde die Idee nicht schlecht, und es ist besser als Passwörter oder PINs versteckt auf kleinen Zettelchen in der Geldbörse zu haben oder in seinem Handy als Notiz.
Jedoch hat der Generator vom Manuel Schmitt einen kleinen Nachteil. Nun gibt es Passwörter / PINs die ich mir nicht merken kann aber auch nicht ändern kann. Sprich ich muss eine Möglichkeit haben, meine vorhandenen Daten in so ein “Zufallsbild” hineinzubekommen. Und daran arbeite ich gerade.
Aktuell kann man sich die Passwortkarte schon generieren, eigene Daten kann man aber noch nicht angeben.
Wenn der Kram fertig ist, gibs ihn hier zum herunterladen!

Recent Comments