Hjemmesiden Firma
Joakim Dalby’s hjemmeside er blevet opbygget efter følgende hensigt:
Til
opfyldelse af hensigten er der truffet følgende valg for opbygning af
hjemmesiden og implementeringen er sker på følgende måde.
Menupunkter
i en database svarer til et simpel Contents Management System der leverer
XML til HTML-genereringen og via XSLT-dokumentet leveres html-tags m.v.
d.v.s. data og præsentation/funktionalitet er adskilt i hver sin fil. Tekster
i Word dokumenter gør det både nemt at forfatte dem med skrifttyper m.v. og senere
at vedligeholde dem, og der kan indsættes billeder og links i dokumentet, så
det til sidst bliver til et egentligt HTML-dokument. Sitemap
er også genereret via et andet XSLT-dokument, der tager det samme XML-dokument
indeholdende menuens data, men omdanner det til et andet HTML-dokument til
præsentation af et sitemap. Det samme XML-dokument bliver således omdannet
via to XSLT-dokumenter til to HTML-dokumenter for selve menuen og for sitemap. Note om bindestreger i Word Den
almindelige bindestreg [-] kaldes på engelsk (regular) hyphen, som har
ansi-værdien #45. Den almindelige bindestreg tillader, at ordet deles over to
linier netop hvor bindestregen står i ordet f.eks. ordet: HTML-dokument, over
to linier: HTML- dokument. Orddelingsbindestreg
[Ctrl][-] kaldes på engelsk optional/soft hyphen, som har ansi-værdien #173.
Orddelingsbindestregen vises kun, når ordet deles over to linier, og med
[Ctrl][-] kan man selv indsætte disse bindestreger, hvis sprog/grammatikken
ikke deler ordet optimalt. Har
man et ord indeholdende bindestreg f.eks. et telefonnummer, eksempelvis 39‑66‑26‑13
og man ikke ønsker, at det deles over to linier, så indsættes bindestregerne
som ikke-orddelingsbindestreger med [Ctrl][Shift][-] kaldet på engelsk nonbreaking
hyphen. I html angives denne bindestreg som &nbhy; eller ‑ Når vi er i gang med
bindestreg, hvorfor så ikke lige nævne tankestregerne: En enkelt tankestreg
kaldes på engelsk en-dash – En dobbelt tankestreg kaldes
på engelsk em-dash — Stored procedure i databasen der danner XML med
menudata CREATE
PROCEDURE dbo.GetXMLMenuList AS BEGIN SET
NOCOUNT ON SELECT
'<?xml version="1.0" encoding="ISO-8859-1"?>' SELECT
'<DALBYXML CreatedDate="' + GetDate() + '"
xmlns="urn:Menu Markup Language">' SELECT
'<MENUMAINLIST>' SELECT
MENUMAIN.MenuMainItem, MENUMAIN.MenuMainActive, MENUDETAILLIST.*, MENUDETAIL.MenuDetailItem,
MENUDETAIL.MenuDetailLink, MENUDETAIL.MenuDetailActive,
MENUDETAIL.MenuDetailSeparator, PAGEMARGIN.MarginWidth FROM
MENUMAIN AS MENUMAIN LEFT OUTER JOIN MENUDETAIL AS MENUDETAIL ON MENUMAIN.MenuMainId =
MENUDETAIL.MenuMainId INNER JOIN SHOWWIDTHTYPELIST AS
PAGEMARGIN ON PAGEMARGIN.ShowWidthType =
MENUDETAIL.ShowWidthType, XMLNULL AS MENUDETAILLIST WHERE
MENUDETAIL.MenuDetailActive = 'ON' ORDER
BY MENUMAIN.MenuMainId, MENUDETAIL.MenuDetailId FOR
XML AUTO, ELEMENTS SELECT
'</MENUMAINLIST>' SELECT
'</DALBYXML>' END Eksempel på den dannet menu XML struktur C# henter XML fra stored procedure, validerer og
gemmer i xml fil using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; using System.Xml; using System.Xml.Schema; using System.IO; private void GetXML() { string connectionstring = "Server=XXX;Database=Homepage;
Integrated
Security=True;Connect Timeout=30"; SqlConnection connection = new SqlConnection(connectionstring); SqlCommand command = new SqlCommand(); command.Connection = connection; connection.Open(); command.CommandType = CommandType.StoredProcedure; command.CommandText = "GetXMLMenuList"; //command.Parameters.Add("Param",
SqlDbType.Int).Value = "8"; //command.Parameters.Add("Status",
SqlDbType.Int).Direction = ParameterDirection.ReturnValue; StringBuilder xmlString = new StringBuilder(); xmlString.Length = 0; SqlDataReader reader = command.ExecuteReader (CommandBehavior.SequentialAccess); do // Flere SELECT danner XML derfor modtages Multiple
Result Sets { while (reader.Read()) // Første gang læses
recordset kolonner og { // peger/pointer flyttes
til første datarække. xmlString.Append(reader.GetString(0)); // Datarækkens
1. kolonne. } // Ved anden gennemløb
læses anden række og } // der fortsættes
indtil alle rækker er læst. while
(reader.NextResult()); reader.Close(); reader.Dispose(); reader = null; //int status = (int)command.Parameters["Status"].Value; //command.Parameters.RemoveAt("Param"); //command.Parameters.RemoveAt("Status"); command.Dispose(); command = null; connection.Close(); connection.Dispose(); connection = null; // Ved fejl i XML
strukturen fås en runtime error der fanges her XmlDocument xmlDoc = new XmlDocument(); XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration ("1.0",
"utf-8", ""); xmlDoc.InsertBefore(xmlDecl,
xmlDoc.DocumentElement); try { xmlDoc.LoadXml(xmlString .ToString()); } catch (XmlException ex) { MessageBox.Show(ex.Message); return; } // Ved fejl i XML i
forhold til schema fås undtagelse der fanges her string xsdFile =
@"C:\Menu.xsd"; //
eksisterende schema indlæses XmlSchemaSet xmlSchema = new XmlSchemaSet(); xmlSchema.Add("urn:Menu Markup Language",
xsdFile); xmlDoc.Schemas.Add(xmlSchema); try { xmlDoc.Validate(new ValidationEventHandler(ValidationEventHandler)); } // Ved fejl i
XML i forhold til XSD udløser Validate en begivenhed catch (Exception ex) { MessageBox.Show(ex.Message); return; } // Gem den
valideret XML fra stored proceduren i en fil string xmlFile = @"C:\Menu.xml"; if (File.Exists(xmlFile))
File.Delete(xmlFile); // BOM (Byte Order
Mark) tre tegn EF BB BF i starten af filen droppes Encoding UTF8EncodingNoBOM = new
UTF8Encoding(false); FileStream fs = File.Open(xmlFile, FileMode.Create, FileAccess.Write,
FileShare.None); StreamWriter sw = new StreamWriter(fs,
UTF8EncodingNoBOM); sw.WriteLine(xmlDoc.OuterXml); sw.Flush(); sw.Close(); fs.Close(); } private static void ValidationEventHandler(object
sender, ValidationEventArgs
args) { throw new Exception(args.Message); // kaster
en undtagelse der } // bliver fanget
(catch) ovenfor. C# validering af en XML fil mod en XML Schema
Definition XSD fil inden den gemmes i en database gennem en stored procedure Godt
at validere indholdet af XML filen inden den skal gemmes i en database ved at
overføre XML indholdet til en stored procedure der så fordeler data ud i
flere tabeller og derved anvender de forskellige tags, elementer og
attributter i XML’en som XSD validerer for at de finder og er opstillet
korrekt. private bool SaveXML() { string xmlFile =
@"C:\Svar.xml"; //Fra Notesblok med danske tegn æøå Encoding ANSIEncoding = Encoding.GetEncoding(1252); //
codepage 1252 //
ISO88591 Encoding.Default FileStream fs = File.Open(xmlFile, FileMode.Open, FileAccess.Read,
FileShare.None); StreamReader sr = new StreamReader(fs,
ANSIEncoding); StringBuilder xmlString = new StringBuilder(); xmlString.Length = 0; string line; while ((line = sr.ReadLine()) != null) { xmlString.Append(line); } line = String.Empty; sr.Close(); fs.Close(); // Ved fejl i XML
strukturen fås en runtime error der fanges her XmlDocument xmlDoc = new XmlDocument(); XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration ("1.0",
"utf-8", ""); xmlDoc.InsertBefore(xmlDecl,
xmlDoc.DocumentElement); try { xmlDoc.LoadXml(xmlString.ToString()); } catch (XmlException ex) { MessageBox.Show(ex.Message); return false; } // Ved fejl i XML
i forhold til schema fås undtagelse der fanges her string xsdFile =
@"C:\Svar.xsd"; //
eksisterende schema indlæses XmlSchemaSet xmlSchema = new XmlSchemaSet(); xmlSchema.Add(null, xsdFile); // null fordi intet targetNamespace xmlDoc.Schemas.Add(xmlSchema); try { xmlDoc.Validate(new ValidationEventHandler(ValidationEventHandler)); } catch (Exception ex) { MessageBox.Show(ex.Message); return false; } // Den korrekt
valideret XML i xmlDoc overføres til stored procedure try { string connectionstring =
"Server=XXX;Database=SVAR;
Integrated Security=True;Connect Timeout=30"; SqlConnection connection = new
SqlConnection(connectionstring); SqlCommand command = new SqlCommand(); command.Connection = connection; connection.Open(); command.CommandType = CommandType.StoredProcedure; command.CommandText = "Save_XML_Svar"; command.Parameters.Add("xml",
SqlDbType.NText).Value = xmlDoc.OuterXml; command.Parameters.Add("Status",
SqlDbType.Int).Direction = ParameterDirection.ReturnValue; command.ExecuteNonQuery(); int status =
(int)command.Parameters["Status"].Value; //MessageBox.Show(status.ToString()); command.Parameters.RemoveAt("xml"); command.Parameters.RemoveAt("Status"); command.Dispose(); command = null; connection.Close(); connection.Dispose(); connection = null; } catch(SqlException ex) { MessageBox.Show(ex.Message); return false; } finally { if (status == 1) // return værdien fra
stored procedure return true; else return
false; } } I stored procedure dannes et xmlDoc objekt ved følgende T-SQL
kommando: EXECUTE sp_xml_preparedocument @xmlDoc
OUTPUT, @xml Det er ikke et krav, at XML filen indeholder encoding men
anvendes <?xml version="1.0"
encoding="ISO-8859-1"?> eller <?xml version="1.0"
encoding="UTF-8"?> giver kommandoen en fejlmelding: »XML parsing error: Switch from
current encoding to specified encoding not supported.« Ønsker man encoding i XML filen kan denne i stedet anvendes: <?xml version="1.0"
encoding="Unicode"?> Stored procedure i databasen der gemmer XML data
i tabeller CREATE PROCEDURE dbo.Save_XML_Svar @xml ntext AS BEGIN SET NOCOUNT ON DECLARE @ForbedringsRapportId int DECLARE @xmlDoc int EXECUTE sp_xml_preparedocument @xmlDoc OUTPUT, @xml INSERT INTO dbo.FORBEDRINGSRAPPORT WITH(ROWLOCK) (OpretDato,
Projektnummer, Afdeling, Litra, Skovnummer, IndsenderNavn) SELECT Getdate(),
Projektnummer, Afdeling, Litra, -- er Skovnummer="" bliver
værdien 0 der her oversættes til NULL CASE WHEN Skovnummer = 0 THEN NULL ELSE Skovnummer END AS Skovnummer, IndsenderNavn FROM
OPENXML(@xmlDoc, '/FORBEDRINGSRAPPORTSVAR/FORBEDRINGSRAPPORT', 1) WITH
(Projektnummer int, Afdeling smallint, Litra nvarchar(5), Skovnummer smallint, IndsenderNavn
nvarchar(50)) IF @@ERROR
<> 0 RETURN(0) SET
@ForbedringsRapportId = SCOPE_IDENTITY() -- giver oprettet Id nr. INSERT INTO dbo.FORBEDRINGSRAPPORTSVAR WITH(ROWLOCK) (ForbedringsRapportId,
ForbedringSpørgsmålId, Rækkefølge, Ja, Nej) SELECT @ForbedringsRapportId,
ForbedringSpørgsmålId, Rækkefølge, Ja, Nej FROM OPENXML(@xmlDoc,
'/FORBEDRINGSRAPPORTSVAR/SVARLISTE/SVAR', 1) WITH
(ForbedringSpørgsmålId int, Rækkefølge int, Ja bit, Nej bit) IF @@ERROR <> 0 RETURN(0) -- Og mere til,
her er bare vist et uddrag af stored proceduren. EXECUTE sp_xml_removedocument @xmlDoc RETURN(1) END Eksempel på
indhold af Svar.xml Eksempel på
indhold af Svar.xsd |