HowTo: PicLens und andere MediaRSS Clients für die eigene Webseite nutzen (MediaRSS mit LINQ to XML erstellen)

Dieses HowTo ist im Zusammenhang mit dem normalen “RSS XLINQ” Post entstanden – ist allerdings wesentlich cooler.

Worum geht es?
Es geht um den “MediaRSS” Standard und wie man diesen für sich nutzen kann. Noch nie davon gehört? Ich bis heute auch nicht.
Allerdings gibt es ein bekanntes Firefox Plugin welches mit darauf basiert – die Rede ist von “PicLens“.

image 

Was kann “PicLens”?
“PicLens” bietet eine sehr schicke Oberfläche für verschiedene bekannte Dienste wie YouTube, Google Bildersuche, Flickr oder auch Amazon:

image
Hier mal die Amazon-Ansicht:

image

Media RSS
PicLens kann auch mit dem oben genannten “MediaRSS” Standard umgehen – auf der Seite ist auch gut beschrieben wie man das macht. Da wir bereits ein RSS Feed mit XLinq erstellt haben, dürfte das ja nicht sonderlich schwerer sein.

XLINQ

Wir haben den selben Projektaufbau – nur in der ASHX müssen wir die Erstellung etwas anpassen:

        XNamespace media = "http://search.yahoo.com/mrss";
        XNamespace atom = "http://www.w3.org/2005/Atom";
        public void ProcessRequest(HttpContext context)
        {

            XDocument document = new XDocument(
                                    new XDeclaration("1.0", "utf-8", "yes"),
                                    new XElement("rss",
                                        new XAttribute("version", "2.0"),
                                        new XAttribute(XNamespace.Xmlns + "media", media),
                                        new XAttribute(XNamespace.Xmlns + "atom", atom),
                                        new XElement("channel", this.CreateElements())
                                       ));

            context.Response.ContentType = "text/xml";
            document.Save(context.Response.Output);
            context.Response.End();
        }

        private IEnumerable<XElement> CreateElements()
        {
            List<XElement> list = new List<XElement>();

            for(int i = 1; i < 100; i++)
            {
                XElement itemElement = new XElement("item",
                                            new XElement("title", i),
                                            new XElement("link", "Code-Inside.de"),
                                            new XElement(media + "thumbnail",
                                                new XAttribute("url", "http://code-inside.de/blog/wp-content/uploads/image-thumb" + i + ".png")),
                                            new XElement(media + "content",
                                                new XAttribute("url", "http://code-inside.de/blog/wp-content/uploads/image-thumb" + i + ".png"))
                                       );
                list.Add(itemElement);
            }

            return list;
        }

In dem ASHX Handler haben wir nun noch zwei zusätzliche XNamespaces deklariert. Diese sind (laut der Piclens Seite) notwendig um erstmal dieses XML zu erzeugen:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss" xmlns:atom="http://www.w3.org/2005/Atom">
...
</rss>

Diese Namespaces werden über ein XAttribute hinzugefügt. Der Syntax ist meiner Meinung nach etwas ungünstig – ein “new XNamespace” oder etwas ähnliches hatte nicht funktioniert. Auch ein “new XElement(’xmlns:media’,'…’)” wurde mit einer Exception belohnt – daher dieser Weg.

In der CreateElement Methode müssen wir nur noch die “media:thumbnail” + “media:content” erstellen und fertig sind wir. Zusätzlich könnte man noch die anderen Elemente des Standards einbauen – schaut einfach nochmal in den Guide.

Ergebnis:
Da wir in unserem Head immer noch den Link zum RSS Feed angegeben haben, prüft PicLens automatisch ob man die Bilder auf der “Wall” anzeigen kann:

image

image 
Wer also viele Bilder auf seiner Webseite hat, könnte dies doch leicht umsetzen – insbesondere da dies ein offener Standard (Specification @ Yahoo) ist und ich davon ausgehe, dass sowas noch häufiger eingesetzt wird. Ob nun PicLens als Client ist ja am Ende auch egal :)

[ Download Source Code ]

PS: Als Bildquelle hab ich mal den Blog genommen – bitte aus Trafficgründen nicht überstrapazieren ;)

HowTo: RSS Feeds mit LINQ to XML erstellen (XLinq)

Ein XML zu erstellen ist mit Linq to XML recht einfach – ähnliches habe ich bereits in diesem HowTo beschrieben.

Der Unterschied ist eigentlich nur in der Verwendung und in dem dynamischen anlegen der Items zu finden.

Hier erstmal der Projektaufbau:

image

Damit unsere Besucher auch auf den RSS Feed aufmerksam werden, hab ich noch im HEAD einen Link auf den RSS-Feed gemacht:

<head runat="server">
    <title>Untitled Page</title>
    <link rel="alternate" href="Rss.ashx" type="application/rss+xml" title="" id="rss" />
</head>

Die “Rss.ashx”:

Das Grundgerüst erzeugen wir direkt in der ProcessRequest Methode:

        public void ProcessRequest(HttpContext context)
        {

            XDocument document = new XDocument(
                                    new XDeclaration("1.0", "utf-8", "yes"),
                                    new XElement("rss",
                                        new XAttribute("version", "2.0"),
                                        new XElement("channel", this.CreateElements())
                                       ));

            context.Response.ContentType = "text/xml";
            document.Save(context.Response.Output);
            context.Response.End();
        }

Hier wird die Deklaration gemacht und das XDocument wird in den Response.Output geschrieben. Unsere Items erzeugen wir an einer anderen Stelle – und zwar in der “CreateElements” Methode.

Die “CreateElements“-Methode:

Diese Methode gibt IEnumberable<XElement> zurück und kann somit direkt in den Baum eingefügt werden:

private IEnumerable<XElement> CreateElements()
        {
            List<XElement> list = new List<XElement>();

            for (int i = 1; i < 100; i++)
            {
                XElement itemElement = new XElement("item",
                                            new XElement("title", i),
                                            new XElement("link", "http://code-inside.de")
                                       );
                list.Add(itemElement);
            }

            return list;
        }

Sehr einfach und schnell gemacht :)

[ Download Source Code ]

HowTo: Generisches speichern und laden von XML Dateien bzw. wozu sind Generics gut?

Immmer wenn ich eine Xml Datei lesen oder schreiben will fange ich wieder an das Code-Snippet dafür zu suchen und an meine Objekttypen anzupassen. Also habe ich mir jetzt mal eine generische Version geschrieben. Das T steht dabei für den noch unbekannten Typ der erst zur Laufzeit übergeben wir.

public static void Save<T>(String path, T obj)
        {
            XmlSerializer Serializer = new XmlSerializer(typeof(T));
            FileStream Stream = new FileStream(path, FileMode.Create);
            Serializer.Serialize(Stream, obj);
            Stream.Close();
        }

        public static T Load<T>(String path)
        {
            XmlSerializer Serializer = new XmlSerializer(typeof(T));
            StreamReader Stream = new StreamReader(path);
            T myObject = (T)Serializer.Deserialize(Stream);
            Stream.Close();
            return myObject;
        }

Der Zugriff erfolgt so:

// Daten
            String TestString = "Hallo Xml Welt";
            //schreiben..
            Save<String>("C:\\test.xml", TestString);
            //und lesen
            Debug.WriteLine(Load<String>("C:\\test.xml"));

Dateien per Namespace aufrufen

Ich hatte ver kurzem das Problem das ich auf eine XML Datei in meinem Projekt zugreifen musste aber den genauen Pfad nicht kannte. Das erzeugen eines dynamischen Pfades per “AppDomain.CurrentDomain.BaseDirectory” war nicht möglich da ich mit Usercontrols arbeitete und so nur den Pfad der Datei bekam die mein Uercontrol einbindet.
Gelöst habe ich das Problem in dem ich über den Namespace auf die XML Datei zugegriffen habe:

// XmlResource  = Namespace + Dateiname
string XmlResource = "CodeInside.WebApp." + "Daten.xml";

  using (Stream FileStream = System.Reflection.Assembly.
    GetExecutingAssembly().GetManifestResourceStream(XmlResource))
  {
    XmlSerializer Ser = new XmlSerializer(typeof(List));
    StreamReader Sr = new StreamReader(FileStream );
    List Data = (List)Ser.Deserialize(Sr);
    Sr.Close();
  }

Damit man auf die Datei auch zugreifen kann muss man in den Eigeschaften der Datei das Feld “Build Action” auf “Embedded Resource” stellen.
Embedded Resource

HowTo: PDFs per Click on-the-fly erstellen

Vor einiger Zeit hat Oliver bereits ein nettes Beispiel gebracht wie man mit nFop ein PDF Dokument erzeugt.

In dem heutigen HowTo geht es darum, PDFs per “klick” auf einem normalen Link zu erzeugen, z.B. wenn man auf einer Webseite einen PDF Export möchte.

Oliver hat mir freundlicherweise sehr geholfen und der Code stammt von ihm :)

Kurze Vorbereitung: J# dlls installieren

Ich hab nur VS 2008 installiert – dabei wurde allerdings wohl die J# Bibliotheken nicht mit installiert – die “vjslib.dll” kann hier aber runtergeladen werden: Visual J# Redistributable Packages

Ein Generic Handler ist die Lösung

Da nFop allerdings auf die J# Bibliothek aufbaut, ist es etwas schwieriger das PDF in den content reinzuschreiben, hier der komplette Code:

<%@ WebHandler Language="C#" Class="PdfHandler" %>

using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using java.io;
using org.xml.sax;
using org.apache.fop.apps;
using System.IO;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class PdfHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "application/pdf";
        FileInputStream input = new FileInputStream(context.Request.PhysicalApplicationPath+"helloworld.fo");
        InputSource source = new InputSource(input);

        java.io.ByteArrayOutputStream output = new ByteArrayOutputStream();

        Driver driver = new Driver(source, output);
        driver.setRenderer(Driver.RENDER_PDF);
        driver.run();
        output.close();

        sbyte[] Pdf = output.toByteArray();
        BinaryWriter bw = new BinaryWriter(context.Response.OutputStream);
        for (int i = 0; i < Pdf.Length; i++)
        {
            bw.Write(Pdf[i]);
        }

        bw.Close();
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Das komplette Projekt sieht so aus:

image

Die helloworld.fo:

<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format”>
  <fo:layout-master-set>
    <fo:simple-page-master  master-name=”A4″
                            page-width=”210mm” page-height=”297mm”>
      <fo:region-body region-name=”xsl-region-body”  margin=”2cm”/>
    </fo:simple-page-master>
  </fo:layout-master-set>

  <fo:page-sequence  master-reference=”A4″>
    <!– (in Versionen <2.0 “master-name”) –>
    <fo:flow flow-name=”xsl-region-body”>
      <fo:block>Hallo Welt!</fo:block>
    </fo:flow>
  </fo:page-sequence>

</fo:root>

Am Ende kann man es einfach über den Link aufrufen:
http://localhost:56602/Pdf/PdfHandler.ashx

Fertig :)

[ Download Democode ]

HowTo: Suchanbieter / Browserplugin für IE7 und Firefox erstellen – die OpenSearchDescription

Vom Firefox und vom IE7 kennen wir diese praktischen Suchfelder:

image

image

Doch wie erstellt man so ein Plugin?

Dafür haben sich die Browserhersteller zusammengesetzt und das "OpenSearchDescription" Format erstellt.

Das ganze habe ich jetzt direkt mal für den Blog erstellt. Das XML sieht dazu wie folgt aus:

 

<?xml version="1.0"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Code-Inside Blog</ShortName>
<Description>Blogging about .NET, ASP.NET, AJAX, Silverlight</Description>
<Image height="16" width="16" type="image/x-icon">http://code-inside.de/blog/wp-content/themes/notso_freshd2/images/favicon.ico</Image>
<Url type="text/html" method="get" template="http://code-inside.de/blog/?s={searchTerms}"/>
</OpenSearchDescription>

Das wichtigste ist eigentlich der "Url" Tag in dem später das Suchwort eingefügt wird – um später direkt auf z.B. http://code-inside.de/blog/?s=AJAX zu kommen.

Einbindung in den Browser

  • Per Javascript:

<a href="#" onclick='window.external.AddSearchProvider("http://code-inside.de/blog/browserplugin.xml");'>Code-Inside Blog</a>

Über den Javascript Aufruf "AddSearchProvider" kann man direkt die Funktion aufrufen und der Browser zeigt dann z.B. so ein Fenster:

image

  • Dem Browser mitteilen, dass es ein Plugin gibt

Bei der zweiten Möglichkeit wird der Browser über diesen Tag direkt über das Plugin informiert:

	<link rel="search" type="application/opensearchdescription+xml" href="http://code-inside.de/blog/browserplugin.xml" title="Code-Inside Blog" />

Damit wird ein Verweis auf das XML gelegt. Im Firefox fängt dann das momentane Icon des Suchenfeldes leicht an zu glühen:

image

Und mit einem Klick kann man den Searchprovider installieren:

image

Im IE7 sieht das ganze ähnlich aus:

image

Einfach und effektiv :)

HowTo: LINQ to XML – Daten schreiben

Zuletzt haben wir bereits über LINQ to XML Daten gelesen, nun wollen wir Daten einfach mal schreiben.

Wie bereits in dem anderen HowTo geschrieben, versteckt sich die gesamte Funktionalität eigentlich im System.Xml.Linq Namespace. In der "prä-.NET 3.5" Zeit hat man über einen XmlWriter oder über XmlDocument mühselig die ganze Struktur aufbauen müssen und (jedenfalls bei XmlDocument) über Append anhängen.

Herzstück der gesamten Demoanwendung ist eigentlich das XElement (für die eigentlichen Xml Elemente) & XAttribut (für Xml Attribute).

Schauen wir uns erstmal das Ergebnis an:

image

Und hier der Code dafür (ich bin immer noch ohne Live Writer Plugin unterwegs, download siehe unten):

image

Dieses Konstrukt sieht vielleicht auf dem ersten Blick seltsam aus, allerdings ist es durch die Formatierung klar und deutlich gegliedert. Max. die Kommas & Klammern muss man beachten.

Der Grund für diese schicke Lösung, liegt in den Konstruktor der XElement Klasse – welche beliebig viele Nodes aufnehmen kann. Das kann man natürlich beliebig fortsetzen.

Das war es schon – jetzt kann man dieses XElement in ein XDocument einbetten und speichern – oder den String speichern etc.

Weitere Infos befinden sich z.B. hier (oder in meinem anderen Blogeintrag).

[ Download Source Code ]

HowTo: LINQ to XML – Daten lesen

LINQ to SQL (siehe hier & hier) habe ich bereits behandelt, doch einer der mitgelieferten LINQ Provider wurde von mir noch vernachlässigt: LINQ to XML.

Ohne LINQ kann man XML über XPath abfragen – das ist eine nette Variante, allerdings vielleicht nicht unbedingt der Weisheits letzter Schluss.

Fangen wir mal langsam an – hier unsere einfache XML Struktur:

image

Wenn man diesen Zweig nun abrufen will, geht folgender Code:

image  
(auf meinem neuen Notebook konnte ich leider noch nicht das CodeFormatting Plugin für den Windows Live Writer installieren – daher nur Screenshots und am Ende gibts den Source Code)

XDocument etc. ist in dem Namespace System.Xml.Linq vorhanden und ist im Grund wie das XmlDokument – natürlich etwas anders. Über die Methode "Descendants" können wir uns entweder (wie oben) manuell durch den Xml Baum hangeln, oder direkt auf das "Item" zugreifen:

image

Ist doch schon wesentlich eleganter, oder? Als Ergebnis bekommen wir bei dieser LINQ Abfrage die XElemente:

image

Jeder Node hat eine "Number" Element, was bei dem ersten Item auf 10, beim zweiten auf 50, beim dritten auf 60 und beim vierten Item auf 70 gesetzt wurde.

Jetzt wollen wir nur mal alle Items heranholen, welche über 55 liegen:

image

Wir navigieren uns wieder zu unseren Items und machen dann anschließend eine Konvertierung des Values im "Number" Tag zu einem Integer.

Am Ende werden nur noch die letzten beiden Item Einträge angezeigt.

Mal etwas komplizierter – Attribute, Verschachtelungen & Abfragen:

Unsere etwas komplexere XML Struktur:

image

Mit dieser LINQ Abfrage bekommt man alle komplexen Items, welche als Attribut "marketplace" "fr" haben und die Number größer als 20 ist:

image

Fazit:

LINQ to XML ist eine schicke Alternative zu normalen XPath und erlaubt sehr viele Spielerein. Wenn ich zeit finde, zeige ich auch noch, wie man XML Dokumente bearbeitet. Man kann das ganze natürlich noch weitertreiben. In dem select Statement kann man sich seine eigenen Datentypen erstellen etc. (dank an das Zauberwort "var").

Insbesondere für diejenigen, welche einen RSS/Atom Feedreader entwickeln wollen, sollten mal auf LINQ to XML einen Blick werfen.

Hier einen weiterführenden Link:

[ Download Source Code ]

HowTo: YouTube mit C# durchsuchen – Einstieg in die YouTube API / Google Data API

Vor einige Zeit habe ich bereits in einem meiner Wöchentlichen Rundablagen diesen interessanten Blogeintrag gefunden: Querying Youtube API using C#

Aufbauend auf diesen, habe ich mich selber mit der YouTube API beschäftigt und schreib mal etwas darüber.

Was kann die YouTube API?

Die YouTube API wurde durch die Übernahme durch Google geändert (siehe YouTube Dev) und ist jetzt Teil der GData API. Die YouTube API basiert auf den ATOM XML Format und kann daher auch ohne Anmeldung oder sonstiges in einem normalen Browser betrachtet werden. Wir suchen einfach mal YouTube nach Videos von U2 über die API ab:

http://gdata.youtube.com/feeds/videos?q=u2

image
(Ergebnis im IE7)

Bietet YouTube / Google sonst noch was?

Da ATOM auch nur XML ist, könnte man jetzt über XmlDocument die Ergebnisse auch selber parsen. Google stellt allerdings für .NET ein SDK bereit, womit man diesen ATOM Feed besser parsen kann: Googles GData .NET Library (einfach das aktuellste nehmen).

Entpackt oder Installiert man das SDK befindet sich in diesem Ordner alle nötigen DLLs: cs\lib\Release

Für die YouTube API gibt es keine gesonderte DLL, sondern wir benötigen diese zwei:

  • Google.GData.Client.dll
  • Google.GData.Extensions.dll

Das tolle Test-Such-Konsolen-Programm

Als Demonstration nehm ich einfach ein Konsolenprogramm – auch wenn dies natürlich bei einer Videosuche etwas “unsinnig” ist – es ist am einfachsten ;)

Folgende Namespaces müssen eingebunden werden (und die 2 DLLs von Google und die System.Web DLL müssen mit referenziert werden):

using System.Web;
using Google.GData.Client;
using Google.GData.Extensions;

Wie bereits weiter oben gezeigt, benötigt man für das Suchen auf YouTube diese URL als Ausgangspunkt: http://gdata.youtube.com/feeds/videos?q=[SUCHWORT]

Das entsprechende “[SUCHWORT]” muss natürlich entsprechend noch für den Einsatz in der URL maskiert werden. Hier hab ich eine schöne Übersicht über die URL-maskier Möglichkeiten im .NET Framework gefunden: URL-Maskierung

Über die Klasse “HttpUtility.UrlEncode” bekommen wir den gewünschten maskierten Suchstring – dafür müssen wir auch “System.Web” mit referenzieren.

Das Test Program bietet einfach eine Eingabemöglichkeit und gibt die 20 ersten Suchtreffer wieder, hier der komplette Quellcode:

        static void Main(string[] args)
        {
            Console.WriteLine("Suchwort:");
            string searchTerm = Console.ReadLine(); 

            string uriSearchTerm = HttpUtility.UrlEncode(searchTerm);
            string url = "http://gdata.youtube.com/feeds/videos?q=" + uriSearchTerm; 

            Console.WriteLine("Connection to YouTube - Searching: " + searchTerm); 

            FeedQuery query = new FeedQuery("");
            Service service = new Service("youtube", "sample");
            query.Uri = new Uri(url);
            query.StartIndex = 0;
            query.NumberToRetrieve = 20;
            AtomFeed resultFeed = service.Query(query); 

            foreach (AtomEntry entry in resultFeed.Entries)
            {
                Console.WriteLine("Title: " + entry.Title.Text);
                Console.WriteLine("Link: " + entry.AlternateUri.Content);
                Console.WriteLine("Tags:");
                foreach (AtomCategory cat in entry.Categories)
                {
                    Console.Write(cat.Term + ", ");
                }
                Console.WriteLine();
            } 

            Console.ReadLine();
        }

Kurz erklärt:

  • Der Suchstring wird über UrlEncode maskiert.
  • “FeedQuery” ist eine spezielle Google.GData Klasse, mit welchem man ATOM Feeds leichter abrufen kann.
  • Bei “Service service = new Service(”youtube”, “sample”)” muss der “Servicename” und der “Applicationname” übergeben werden, obwohl dies wohl keinerlei Bedeutung hat.
  • Bei “service.Query(query)” wird die Suchanfrage abgeschickt (max. Suchergebnisse sind wohl 20 Einträge pro Request) und als Ergebnis kommt ein “AtomFeed”.
  • Dieser “AtomFeed” wird pro Entity entsprechend ausgegeben.
  • Die für YouTube interessante “watch” Adresse, versteckt sich in entry.AlternAteUri.Content – z.B. http://www.youtube.com/watch?v=w-TssRlmmBE für einen U2 Song

Resultat für die Suchanfrage für “Die Ärzte”:

image

Der Sourcecode wurde nur wenig vom originalen abgeändert.

Was macht man nun damit?

Das ganze bringt momentan in der Konsolenanwendung relativ wenig – in einer Windows.Forms Anwendung und mit dem “WebBrowser” in dem das Flashfile abgespielt werden kann, ist das schon brauchbarer (oder in einer ASP.NET Anwendung)

Leider gibt es wohl keine Möglichkeit (jedenfalls nicht mit dieser API – weiß einer einen anderen Weg?) das Flash von außen zu steuern. Das heisst, das man das embedded HTML (wie es bei YouTube üblich ist) immer mit einbauen muss – dafür kann man z.B. gut das “WebBrowser” Control nehmen.

Das Demoprojekt runterlade

Runterladen könnt ihr das Demoprojekt natürlich auch – ich hab es diesmal mit dem Visual Studio 2008 (die Express Edition kann jeder sich kostenlos runterladen) erstellt – falls jemand nur Visual Studio 2005 zur Hand hat und den Code benutzen möchte, steht dem nichts im Wege – einfach die CS Datei öffnen. In dem Demoprojekt wird kein .NET 3.5 benötigt – ich wollte nur mal rumexperimentieren.

[Download Democode]

Links:

HowTo: PDF’s erstellen unter .NET mit NFop

Wenn man ein PDF erstellen möchte, hat man die Auswahl zwischen vielen kommerziellen Produkten für .NET - mit NFop möchte ich mal eine kostenlose Möglichkeit vorstellen.
NFop ist eine Portierung der Open Source Java Anwendung FOP auf .NET und dank J# kann der Quellcode auch direkt unter dem .NET Framework kompiliert werden. NFop wandelt XML Formatting Objects (XML-FO) Dokumente in PDF Dateien um. In der Regel erzeugt man die XML-FO Dokumente mit Hilfe von XSLT aus einem XML.

.NET Anwendung -> XML + XSLT -> XML-FO -> PDF

Durch Austauschen des XSLT’s kann man so einfach die Formatierung ändern, ähnlich wie bei HTML und CSS. Wie man aus seinem Datenbestand ein XML generieren kann finden sie hier.

Weil ich den NFop Code nicht ändern wollte habe ich die DLL einmal erstellt und dann in mein Projekt eingebunden. Für dieses Beispiel muss man zusätzlich noch die vjslib einbinden. Wenn man raus gefunden hat welche Namespaces man einbinden muss geht das Erstellen des PDF’s mit wenigen Zeilen Code. Weil ich das Beispiel übersichtlich halten wollte habe ich auf XSLT verzichtet und nur das XML-FO Beispiel von Wikipedia benutzt.

using java.io;
using org.xml.sax;
using org.apache.fop.apps; 

namespace XmlToPdf
{
    class Program
    { 

        static void Main(string[] args)
        {
            //erstellen eines einfachen PDFs
            ConvertFoDocument("helloworld.fo", "helloworld.pdf", Driver.RENDER_PDF);
        } 

static void ConvertFoDocument(string foFile, string pdfFile,int outputType)
        {
            FileInputStream input = new FileInputStream(foFile);
            InputSource source = new InputSource(input);
            FileOutputStream output = new FileOutputStream(pdfFile); 

            Driver driver = new Driver(source, output);
            driver.setRenderer(outputType);
            driver.run(); 

            output.close();
        } 

    } 

}

die helloworld.fo

<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <fo:layout-master-set>
    <fo:simple-page-master  master-name="A4"
                            page-width="210mm" page-height="297mm">
      <fo:region-body region-name="xsl-region-body"  margin="2cm"/>
    </fo:simple-page-master>
  </fo:layout-master-set>

  <fo:page-sequence  master-reference="A4">
    <!-- (in Versionen <2.0 "master-name") -->
    <fo:flow flow-name="xsl-region-body">
      <fo:block>Hallo Welt!</fo:block>   
    </fo:flow>
  </fo:page-sequence>

</fo:root>

Resultat:
Als Ergebniss bekommt man ein PDF mit “Hello World!”.

Den kompletten Beispielcode kann man hier herunterladen:
XmlToPdf Projekt

HowTo: XML erstellen mit XmlAttributes

Es gibt viele Möglichkeiten ein XML mit .NET zu erstellen. Eine sehr praktische und schnelle Möglichkeit ist die XmlAttributes-Variante zu verwenden.
Oft hat man schon ein Objektmodell das man als XML ausgeben oder eine XML Datei die man in sein Objektmodell einlesen möchte. Für diese Aufgaben ist der XmlSerializer ideal.

Ein einfaches Schreiben:

 XmlSerializer _xmlGen = new XmlSerializer(typeof(string));
            _xmlGen.Serialize(Console.Out,"www.code-inside.de");

 

Erklärung: Wir serializieren hier einfach den String www.code-inside.de auf der Console und schauen uns an was passiert:

image

So wird es auf der Kommandozeile ausgegeben.

Ein einfaches Lesen:

XmlSerializer _xmlGen = new XmlSerializer(typeof(string));
            Console.WriteLine(
                _xmlGen.Deserialize(
                       new StringReader("<string>www.Code-Inside.de</string>")));

Erklärung: Diesmal wollen wir einfach unser XmlTag (mit dem Code-Inside.de), was rein theoretisch z.B. in einer Datei stehen könnte) wieder lesen.

image

Da ist wieder unser ursprünglicher String ;)

 

Man kann natürlich nicht nur Strings serialisieren, sondern auch komplexere Objekte.
Wichtig: Diese Klassen müssen dann “public” sein und einen leeren Konstruktor haben.

Wenn man Objekte serialisiert dann werden die Elemente im XML nach dem Variablennamen oder dem Datentypen des serialisierten Objektes benannt, weil dies aber nur selten sinnvoll ist, gibt es die Möglichkeit die Ausgabe über Attribute zu steuern.
Eine Liste der XmlAttribute findet sich natürlich auf der MSDN.

Klassenstruktur für unser Beispielprojekt:

image

(auch wenn Oliver, welcher den Artikel vorbereitet & zum großen Teil geschrieben hat, das alles in die Program.cs mit reinschreiben wollte ;) )

Der Code ist einfach gehalten. Über den einzelnen Eigenschaften wurde, wie z.B. beim Title des BlogEntry, das XmlAttribute gesetzt:

        [XmlElement("title")]
        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }

Sowie über den Klassennamen des BlogEntrys das XmlRootAttribute:

[XmlRootAttribute("BlogEntry")]
    public class BlogEntry

Das Schreiben wurde ähnlich Implementiert wie bei dem simplen Beispiel:

 BlogEntry _myBlogEntry = new BlogEntry();
      _myBlogEntry._title = "XML erstellen mit XmlAttributes";
      _myBlogEntry._content = "Es gibt viele Möglichkeiten...";
      for (int i = 0; i < 2; i++)
      {
         _myBlogEntry._comments.Add(new BlogComment("Paul","Cooole Sache"));
         _myBlogEntry._comments[i]._comments.Add(new BlogComment("Tim", "Finde ich auch Paul"));
      }
      _xmlGen.Serialize(Console.Out, _myBlogEntry);

Wir erstellen ein Blogeintrag und hängen noch ein paar Blogkommentare dran und schreiben das auf die Konsole. In unserer Demoanwendung später, werden wir dies allerdings in eine Datei speichern, welche im bin Verzeichnis zu finden ist..

Das resultierende Xml daraus:

<?xml version="1.0" encoding="UTF-8"?>
<BlogEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http ://www.w3.org/2001/XMLSchema">
  <Title>XML erstellen mit XmlAttributes</Title>
  <content>Es gibt viele Möglichkeiten...</content>
  <comments name="Paul">
    <content>Cooole Sache</content>
    <comments name="Tim">
      <content>Finde ich auch Paul</content>
    </comments>
  </comments>
  <comments name="Paul">
    <content>Cooole Sache</content>
    <comments name="Tim">
      <content>Finde ich auch Paul</content>
    </comments>
  </comments>
</BlogEntry>

Das Lesen erfolgt ähnlich wie bereits oben erwähnt. In der Demoanwendung sieht das Ergebniss beim Ausführen so aus:

image

 

Fazit: MIt dem XmlSerializer und XmlAttributes lassen sich auch komplexe XML Dateien sehr schnell, einfach und übersichtlich lesen und schreiben, besonders bei rekursiven Strukturen zeigen sich deutliche Vorteile gegenüber dem XmlTextWriter.

[ Download Democode ]

HowTo: Xml mit Javascript Parsen (Zugriff auf Nodes & Attribute)

JSON ist eigentlich eine feine Sache – allerdings hat man manchmal keine Wahl und muss in Javascript ein XML parsen.

Das dies eigentlich fast genauso einfach ist, wie JSON, sieht man allerdings erst hinterher. Da der Zugriff manchmal allerdings etwas blöder ist als unter .NET selbst, schreibe ich kurz dieses HowTo. Die Demoanwendung samt kompletten Sourcecode gibts am Ende.

Vorbereitung: ASP.NET AJAX Projekt, XML Datein samt Webservice mit “ScriptService” versehen und einbinden

Unsere Demoappliaktion ist sehr einfach – das Hauptaugenmerk liegt sowieso später auf dem Javascript:

image

Die 3 XML Datein werden wir mit Javascript auswerten:

“Example_1.xml”

<?xml version="1.0" encoding="utf-8" ?>
<root>FooBar</root>

“Example_2.xml”

<?xml version="1.0" encoding="utf-8" ?>
<root>
   <itemCollection>
      <item>FooBar1</item>
      <item>FooBar2</item>
      <item>FooBar3</item>
   </itemCollection>
</root>

“Example_3.xml”

<?xml version="1.0" encoding="utf-8" ?>
<root>
   <itemCollection category="Products">
      <item id="1234523">
         <title>Foo1</title>
         <subtitle>Bar1</subtitle>
      </item>
      <item id="123797590">
         <title>Foo2</title>
         <subtitle>Bar2</subtitle>
      </item>
      <item id="889774395">
         <title>Foo3</title>
         <subtitle>Bar3</subtitle>
      </item>
   </itemCollection>
</root>

Wie man sieht – am Ende ist quasi die Königsdisziplin dran – verschachtelte Elemente und Attribute.

Der Webservice hat folgende Methode:

        [WebMethod]
        [ScriptMethod(ResponseFormat=ResponseFormat.Xml)]
        public XmlDocument LoadExample(int id)
        {
            string filename = "Example_" + id.ToString() + ".xml";
            string path = Path.Combine(this.Context.Request.PhysicalApplicationPath, filename); 

            XmlDocument ExampleDocument = new XmlDocument();
            ExampleDocument.Load(path); 

            return ExampleDocument;
        }

Achtung: Da die AJAX Extensions (siehe auch dazu hier die Grundlagen) immer ein Json zurückgeben, muss man erst das “ResponseFormat” auf “ResponseFormat.Xml” stellen.
Ansonsten einfaches einlesen der einzelnen XML “Example_X.xml” Datein und über den Webservice zurückgeben.
Diesen Webservice jetzt noch als Scriptservice im Scriptmanager bekannt machen und gut ist (das dazugehörige HowTo).

Einfaches Interface basteln

image

Das sehr einfache Interface besteht aus einer Überschrift und 3 Buttons welche die AJAX Requests starten, damit wir im Anschluss das XML auswerten können.
Unter den Buttons erfolgt dabei die Ausgabe und eine kurze Erklärung was da passiert.

Javascript: Example_1.xml parsen (einfacher Javascript Zugriff auf ein Element)

var myResult = result.getElementsByTagName("root")[0].firstChild.nodeValue;

Das ist der Zugriff auf unser “nodeValue” “FooBar”. In dem Screenshot kann man den Verlauf auch folgen: 

image 
(Ausschnitt aus dem Firebug – siehe dazu HowTo JS debuggen)

Erklärung:

getElementsByTagName: Liefert alle Nodes mit den übergebenen Namen zurück
getElementsByTagName(”root”)[0]: Liefert das erste vorkommen dieses Nodes zurück
firstChild: Liefert auch das erste Vorkommen eines Nodes zurück – wenn man aber auf den Value des Nodes Zugreifen will, muss man vorher ebenfalls über firstChild und dann erst nodeValue rein (siehe Screenshot)

Javascript: Example_2.xml parsen (Javascript Zugriff auf mehrere Element)

                var myResult = "";
                for(i = 0; i < result.getElementsByTagName("item").length; i++)
                    {
                    myResult += result.getElementsByTagName("item")[i].firstChild.nodeValue + "<br/>";
                    }

Erklärung:

Hier macht man sich den selben Mechanismus zunutze, diesmal fragt man allerdings vorher die Anzahl der gefunden Nodes über “getElementsByTagName(’xxx’).length” ab.
Dannach wieder jede Node durchgehen und auf unseren Inhalt über “firstChild.nodeValue” zugreifen.

Javascript: Example_3.xml parsen (Javascript Zugriff auf Xml Attribute)

Da es ja auch vorkommt, dass Attribute mit in den Nodes vorhanden sind, können diese natürlich ebenfalls über Javascript abgerufen werden:

result.getElementsByTagName("itemCollection")[0].getAttribute("category")

Über die Methode “getAttribute” wird direkt der gefundene Value des Attributes zurückgegeben. Eine andere (aber nicht so schöne) Möglichkeit ist über “element.attributes[0].value” – alledings geht “element.attributes["category"].value” nicht (jedenfalls bei mir gerade nicht).

Getestet alles mit IE 7 und Firefox 2 – sollte aber generell bei allen Browsern so funktionieren.

[ Source Code | Demoapplikation* ]

* auf dem Webspace funktioniert es momentan noch nicht so wie lokal – hängt mit dem Hoster zusammen – einfach die Demoapp runterladen und freuen ;)

Links:

HowTo – ASP.NET AJAX Grundlagen
HowTo – Clientseitiger Aufruf von Webmethoden
HowTo – JS debuggen

Neues HowTo, "Neue" Guides

Hallo,

ich hab mal wieder mich hingesetzt und neben den MS ASP.NET AJAX HowTos jetzt auch eine neue Reihe angefangen (allerdings hängen die auch mehr oder weniger mit zusammen ;) ) – Silverlight.

Ich hab auch den XML Guide erweitert mit 4 neuen Seiten. Dabei hab ich gemerkt, dass ich wohl an die Grenzen von Wordpress gestoßen bin, daher ist die Formatierung etwas zerschossen im Firefox, weil ich die eine Seite in drei Teile aufspalten musste. Leider. Und mein Browser ist mehrmals abgestürtzt. Ich muss mal forschen, woran das liegt oder muss mir eine neue Struktur überlegen.

Bis dahin allerdings die 4 Guide-Teile:

Guide: XML (DocumentType Definitions DTDs)
Guide: XML (XML Schema – Teil 1)
Guide: XML (XML Schema – Teil 2)
Guide: XML (XML Schema – Teil 3)

 

Grüße,

Robert

Guide: XML (XML Schema XSD – Teil 2)

4.2.2.3 Definition von Typen

Jedem Element und Attribut werden Typen zugeordnet. In der XSD gibt es einfache („simpleType“) und komplexe(„complexType“) Typen.

Einfache Typen “simpleType”:

Der „simpleType“ definiert einen einfachen Typ, welcher bereits vordefinierte Typen, wie z.B. xsd:string, xsd:int etc. enthält.

Es ist auch möglich, eigene einfache Typen zu schaffen, allerdings müssen diese auf einfachen, schon vordefinierten Typen bestehen und diese einschränken.

Beispiel in XSD:
<?xml version=”1.0” encoding=”UTF-8”?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
…
<xsd:simpleType name=“waehrung“>
   <xsd:restriction base=”xsd:string”>
            <!--Facette -->
   </xsd:restriction>
   </xsd:simpleType>
</xsd:schema>

 

In dem Falle haben wir einen einfachen Typ namens „waehrung“ geschaffen, welcher über xsd:restriction Beschränkungen enthält, allerdings basiert („base“) dieser Typ „waehrung“ auf den vordefinierten Typ „xsd:string“, wobei dann durch so genannte Facetten die Beschränkung erfolgt.

 

Komplexe Typen “complexType”:

Komplexe Datentypen erlauben in XML die Kindelemente eines Elementes zu beschreiben.

Beispiel:
<xsd:element name="Name" type=”name”>
   <xsd:complexType>
      <xsd:sequence>
         <xsd:element name="Vorname" type="xsd:string"/>
         <xsd:element name="Nachname" type="xsd:string"/>
        </xsd:sequence>
   </xsd:complexType>
</xsd:element>

Hiermit weise ich dem Element „Name“ den Typ „Name“ zu. Da es diesen Datentyp noch nicht gibt, muss er erst beschrieben werden, welche Elemente er enthält.

Das hier angegebene Beispiel bedeutet, dass das Element „Name“, 2 Kindelemente hat.

Einfacher Inhalt “simpleContent”:

Der „simpleContent“ definiert einen einfachen Inhalt, was bedeutet, dass er nur Text enthalten darf.

Komplexer Inhalt “complexContent”:

Der „complexContent“ definiert einen komplexen Inhalt, was bedeutet, dass er Text, Attribute und andere Elemente enthalten darf.

 

4.2.2.4 Definition des Inhaltes

 

4.2.2.4.1 Sequenz

Merkmale:

  • Elemente müssen der Reihe nach vorkommen.
  • Falls keine anderen Werte angegeben werden, können Elemente 0 oder mehrfach vorkommen.
Beispiel:
<xsd:element name="Anschrift" type=”anschrift”>
   <xsd:complexType name=”anschrift”>
      <xsd:sequence>
         <xsd:element name="wohnort" type="xsd:string"/>
         <xsd:element name="plz" type="xsd:int"/>
         <xsd:element name="strasse" type="xsd:string"/>
         <xsd:element name="nr" type="xsd:int"/>
         <xsd:element name="name" type="xsd:string"/>
        </xsd:sequence>
   </xsd:complexType>
</xsd:element>

 

4.2.2.4.2 Choice

Merkmale:

  • Aus einer Anzahl von Elementen darf, falls kein anderer Wert über Max/MinOccurs gesetzt, ein Element vorkommen. Ansonsten auch mehrere möglich.
  • Reihenfolge beliebig.
  • Durch das MaxOccurs ist es möglich zu sagen, dass Elemente mehrfach und die Reihenfolge beliebig ist
Beispiel:
<xsd:element name="Tier" type=”tier”>
   <xsd:complexType name=”tier”>
      <xsd:choice>
         <xsd:element name="Affe" type="xsd:string"/>
         <xsd:element name="Tiger" type="xsd:string "/>
         <xsd:element name="Leopard" type="xsd:string"/>
         <xsd:element name="Maus" type="xsd:string "/>
        </xsd:choice>
   </xsd:complexType>
</xsd:element>
4.2.2.4.3 All

Merkmale:

  • Jedes Element darf einmal vorkommen.
  • Reihenfolge spielt keine Rolle.
Beispiel:
<xsd:element name="Einkaufsliste" type=”einkaufsliste”>
   <xsd:complexType name=”einkaufsliste”>
      <xsd:all>
         <xsd:element name="Kaese" type="xsd:string"/>
         <xsd:element name="Milch" type="xsd:string "/>
         <xsd:element name="Butter" type="xsd:string"/>
         <xsd:element name="Wurst" type="xsd:string "/>
        </xsd:all>
   </xsd:complexType>
</xsd:element>

 

4.2.2.4.4 Group

Merkmale:

  • Gruppiert eine Reihe von Elementen oder Anweisungen.
Beispiel:
<xsd:complexType name="BestellungTyp">
  <xsd:sequence>
    <xsd:choice>
      <xsd:group ref="verschiedeneAdr"/>
      <xsd:element name="eineAdresse" type="DeAdresse"/>
    </xsd:choice>
    <xsd:element ref="Kommentar" minOccurs="0"/>
    <xsd:element name="Waren" type="WarenTyp"/>
  </xsd:sequence>
  <xsd:attribute name="bestelldatum" type="xsd:date"/>
</xsd:complexType>

<xsd:group name="verschiedeneAdr">
  <xsd:sequence>
    <xsd:element name="Lieferadresse" type="DeAdresse"/>
    <xsd:element name="Rechnungsadresse" type="DeAdresse"/>
  </xsd:sequence>
</xsd:group>

 

4.2.2.4.5 Any

Merkmale:

  • Erlaubt beliebigen Datentyp
4.2.2.4.6 Extensions

Extension bedeutet auf Deutsch Ableitung. Das Prinzip was dahinter steckt, ist bereits aus der Programmierung bekannt – Stichwort lautet Vererbung.

Ableitungen von Elementtypen sind dann interessant, wenn man manche Elemente spezialisieren möchte. Man spart sich dadurch eine Menge Tipparbeit und man kann einfach andere Kindelemente an das Elternelement dranhängen. Als Beispiel möchte ich hier die Einkaufsliste erweitern.

Beispiel:
<xsd:complexType name=”myEinkaufsliste”>
   <xsd:complexContent>
      <xsd:extension base=”einkaufsliste”>
         <xsd:all>
         <xsd:element name="Fertigesssen" type="xsd:string"/>
           </xsd:all>
      </xsd:extension>
   </xsd:complexContent>
</xsd:complexType>

 

4.2.2.4.7 Restrictions

Man kann auch einen neuen Elementtypen erzeugen, indem man einen bereits vorhandenen Elementtyp beschränkt. Dafür müssen alle Elemente aufgezählt werden und dabei kann man beliebig die Beschränkungen verteilen.

Als Beispiel möchte ich mein Anschriftsschema von oben verwenden.

Beispiel:
<xsd:complexType name=”singelAnschrift”>
   <xsd:restriction base=“anschrift“>
      <xsd:sequence>
         <xsd:element name="wohnort" type="xsd:string"/>
         <xsd:element name="plz" type="xsd:int"/>
         <xsd:element name="strasse" type="xsd:string"/>
         <xsd:element name="nr" type="xsd:int"/>
         <xsd:element name="name" type="xsd:string" minOccurs=”1” maxOccurs=”1”/>
        </xsd:sequence>
   </xsd:restriction>
</xsd:complexType>

Bei dem Beispiel muss immer ein Element “name” vorkommen.

Liste der Einschränkungen, auch Facetten genannten, durch welche man einfache Beschränkungen realisieren kann:

  • length, maxLength, minLength – Länge eines Strings
  • enumeration – Auswahl
  • pattern – Reguläre Ausdrücke
  • minExclusiv, maxExclusiv, minInclusiv, maxInclusiv – Wertebereicheinschränkung
  • totalDigits, fractionDigits – Einschränkung der Dezimalstelle (Gesamtzahl, Nachkommastelle)
  • whiteSpace – Behandlung von Tabs und Leerzeichen
Beispiel:
<xsd:simpleType name=”IQ”>
   <xsd:restriction base=“xsd:decimal“>
      <xsd:minInclusiv value=”80”/>
      <xsd:maxInclusiv value="180"/>
      <xsd:fractionDigits value=”3”/>
   </xsd:restriction>
</xsd:simpleType>

 

4.2.2.4.8 List

In einem XML Element können durch den Typ Liste mehrere “pseudo”-Elemente drin stehen. Die Elemente müssen allerdings alle vom selben Typ sein.

Beispiel:
<xsd:simpleType name="BundeslandListe">
    <xsd:list itemType="Bundesland"/>
</xsd:simpleType>

<xsd:simpleType name="SechsBundesländer">
    <xsd:restriction base="BundeslandListe">
    <xsd:length value="6"/>
    </xsd:restriction>
</xsd:simpleType>

Beispiel:
<sechsLänder>Sachsen       Baden-Württemberg   Rheinland-Pfalz
             Brandenburg   Niedersachsen       Hessen</sechsLänder>

 

4.2.2.4.9 Union

Die Union bietet in der XSD die Möglichkeit einem Element mehrere Typen zu geben, sodass man ähnlich zur Liste, mehrere „pseudo“ Elemente in einem Tag hat.

Syntax: <xsd:union memberTypes=“Typen“ />

Beispiel:
<xsd:simpleType name="Irgendwas">
   <xsd:union memberTypes=“xsd:int xsd:string“/>
</xsd:simpleType>

Beispiel:
<Irgendwas>12 Bla</Irgendwas>
<Irgendwas>12</Irgendwas>
<Irgendwas>12 Bla 12</Irgendwas>
<Irgendwas>Bla Bla</Irgendwas>

 

4.2.2.4.10 AnyAttribute

Erlaubt beliebige Attribute innerhalb von Elementen.

4.2.2.4.11 AttributeGroup

Gruppiert Attribute, sodass ein einfacher Zugriff auf diese möglich ist.

 

Guide: XML (XML Schema XSD – Teil 3)

4.2.2.5 Elemente für Schlüssel

In der XSD gibt ebenso wie in der DTD die Möglichkeit einmalige Schlüssel, ähnlich wie der Index in einer Datenbank, zu definieren.

In XSD gibt es fünf Arten, die hier kurz vorgestellt werden:

  • xsd:key
    • eindeutige Schlüsselwerte
  • xsd:field
    • gibt Gültigkeitsbereich an
  • xsd:unique
    • optional, muss aber eindeutig sein
  • xsd:refkey
    • Referenz auf den Schlüssel
  • xsd:selector
    • gibt Gültikeitsbereich mit XPath an

 

4.2.2.6 Modularisierung

Modularisierung in der XSD erlaubt, dass gewisse Teile immer wieder verwendet werden können und somit diese wesentlich besser nutzen kann. XSD kennt drei Arten, eine andere XSD zu importieren.

 

xsd:include

Typdefinitionen innerhalb eines Namensraumes, die auf mehrere Dateien verteilt sind, lassen sich mittels include zusammenfügen.

Beispiel:
<schema xmlns="http://www.w3.org/2001/XMLSchema"
         xmlns:pcTeile="http://www.example.com/pcTeile"
         targetNamespace="http://www.example.com/pcTeile">
   ...
   <include schemaLocation="http://www.example.com/schemata/harddisk.xsd">
   <include schemaLocation="http://www.example.com/schemata/ram.xsd">
   ...
 </schema>

 

xsd:import

Der import-Tag erlaubt es, Elemente aus anderen Namensräumen zu importieren, mit einem Präfix zu versehen und damit Schema-Bestandteile aus unterschiedlichen Namespaces wiederzuverwenden.
Annahme ist, dass es einen definierten Typ “superTyp” in “pcTeile” gibt.

Beispiel:
<schema xmlns="http://www.w3.org/2001/XMLSchema"
         xmlns:pcTeile="http://www.example.com/pcTeile"
         targetNamespace="http://www.example.com/firma">
   ...
   <import namespace="http://www.example.com/pcTeile"/>
   ...
     <...
       <xsd:attribute name="xyz" type="pcTeile:superTyp"/>
     .../>
   ...
 </schema>

xsd:redefine

Gleiches Beispiel wie gerade. Annahme es gäbe einen complexType “Hersteller” im Schema “harddisk.xsd”".

Beispiel:
<schema xmlns="http://www.w3.org/2001/XMLSchema"
         xmlns:pcTeile="http://www.example.com/pcTeile"
         targetNamespace="http://www.example.com/pcTeile">
   ...
   <redefine schemaLocation="http://www.example.com/schemata/harddisk.xsd">
     <complexType name="Hersteller">
       <complexContent>
         <restriction base="pcTeile:Hersteller">
           <xsd:sequence>
             <xsd:element name="hersteller" type="xsd:string" minOccurs="10" maxOccurs="10"/>
           </xsd:sequence>
         </restriction >
       </complexContent>
     </complexType>
   <redefine/>
   ...
   <include schemaLocation="http://www.example.com/schemata/ram.xsd">
   ...
 </schema>

 

4.2.2.7 Dokumentation

In der XSD gibt es die Möglichkeit zu den einzelnen Elementen oder auch generell zur XSD eine Art Kommentare zu erstellen. Diese werden hier kurz aufgelistet.

  • xsd:annotation
    • sind Anmerkungen
  • xsd:documentation
    • dient der Dokumentation
  • xsd:appinfo
    • gibt Information über Applikation

 

4.2.2.8 Facetten

Beim Thema der Beschränkung ist schon kurz der Begriff der Facetten gefallen. In der XSD gibt mehrere Arten der Beschränkung.

  • xsd:length
    • Gibt die genaue Länge eines Strings an
  • xsd:maxLength
    • Maximale Länges eines Strings
  • xsd:minLength
    • Minimale Länge eines Strings
  • xsd:pattern
    • Reguläre Ausdrücke
  • xsd:maxExclusive
    • Setzt eine obere Schranke für numerische Werte. Werte müssen kleiner sein.
  • xsd:minExclusive
    • Setzt eine untere Schranke für numerische Werte. Werte müssen größer sein.
  • xsd:minInclusive
    • Setzt eine untere Schranke für numerische Werte. Werte müssen größer oder gleich groß sein.
  • xsd:maxInclusive
    • Setzt eine obere Schranke für numerische Werte. Werte müssen kleiner oder gleich groß sein.
  • xsd:enumeration
    • Definiert eine Liste möglicher Werte
  • xsd:whiteSpace
    • Definiert wie white Spaces behandelt werden sollen
  • xsd:totalDigits
    • Gibt die exakte Anzahl der Ziffern an.
  • xsd:fractionDigits
    • Definiert die max. Erlaubten Dezimalstellen

 

4.2.3 Datentypen

Komplexe Datentypen haben wir ja schon kennen gelernt, aber die Frage, welche Datentypen direkt von der XSD unterstützt werden, ist noch nicht ganz geklärt.

XML Schema stellt einige einfache Datentypen bereit, welche auch schon aus anderen Programmiersprachen bekannt sind.

Hier ein kleine Auswahl über die wichtigsten Datentypen:

  • string – „Test“
  • decimal – 23.3
  • boolean – true/false
  • data – Jahr/Monat/Tag (2006-12-05)
  • time – Stunde/Minute/Sekunde/Hundertstel (21:03:43.03)
  • datetime – Jahr/Monat/Tag Stunde/Minute/Sekunde (2006-02-23T23:23:23) „T“=Trennzeichen
  • float – -23.6
  • anyURI – eine URI (http://www.heise.de)
  • gYearMonth – Jahr/Monat (2005-12)
  • gMonthDay – Monat/Tag (12-05)
  • gYear – Jahr (2005)
  • gMonth – Monat (12)
  • gDay – Tag (12)
  • hexBinary – Hexadezimaler Wert (12EA)
  • language – Sprachbezeichnung (de-DE)
  • QName – Qualifizierter Name innerhalb eines Namensraumes
  • ID – Identifikationsattribut innerhalb eines XML
  • IDREF – Referenz auf ID
  • Integer – 12
  • positivInteger – 12
  • negativInteger – -12
  • long – -9223372036854775808 bis 9223372036854775808
  • int – -2147483648 bis 2147483647 32-Bit Integer
  • byte – -127 bis 128 8-Bit Integer

 

Beispiel:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" elementFormDefault="qualified">
   <xsd:element name="p" type="xsd:string"/>
</xsd:schema>

 

4.2.4 Namensräume in der XSD

Namensräume, welche in dem XML Dokument angeben werden, finden sich auch in der XSD wieder.

Der vollständige Namespace wird im Attribut „targetNamespace“ festgehalten.

Beispiel:
<schema targetNamespace="http://www.example.com/BEST"/>
…
</schema>

 

4.3 Andere Schemaarten

 

Die DTD und die XSD sind direkt vom W3C, allerdings gibt es noch zwei andere bekannte Schemasprachen, welche auch auf XML aufbauen.

  • Relax NG
  • WSDL