XML
Databinding
XSLT
AJAX
Børre Stenseth
Moduler>AJAX>AJAX i .NET>Noen viner

Utvalg av viner

Hva
screen
Utvalg av viner, type og land

I denne modulen skal vi lage en vevside som lar oss finne et antall viner basert på land og vintype. Datakilden er en XML-fil med vinbeskrivelser.

Dette er en AJAX-løsning av det du finner som en desktop applikasjon på modulen: XML og Vin

Råmaterialet er beskevet i modulen Noen datasett, og er en XML-fil som som ser slik ut:


<?xml version="1.0" encoding="UTF-8"?>
<wines>
    <wine>
        <type>sparkling</type>
        <name>Gosset Grande Réserve Brut</name>
        <catalog>32299</catalog>
        <country>Frankrike</country>
        <volume>75</volume>
        <price>259.00</price>
        <dice>5</dice>
        <description>Syrefrisk og harmonisk smak med god fylde.</description>
    </wine>
    ...
</wines>

Du kan se løsningen her:

http://donau.hiof.no/borres/dn/AjaxVin/http://donau.hiof.no/borres/dn/AjaxVin/

Default.aspx

Default.aspx - fila i sin helhet er slik:

<%@ Page Language="C#" AutoEventWireup="true"  
         CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html 
         PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Viner</title>
    <link href="vin.css" rel="Stylesheet"/>
</head>
<body>
<h1>Noen viner</h1>
<hr />
<form id="form1" runat="server">
<table>
<tr>
<td  valign="top">
    <div class="choice">
    Land: <asp:DropDownList ID="DropDownListCountry" runat="server">
    </asp:DropDownList>
    </div>
    <div class="choice">
    Type: <asp:DropDownList ID="DropDownListType" runat="server">
            <asp:ListItem Value="red">Rød</asp:ListItem>
            <asp:ListItem Value="white">Hvit</asp:ListItem>
            <asp:ListItem Value="sparkling">Musserende</asp:ListItem>
            <asp:ListItem Value="rose">Rose</asp:ListItem>
    </asp:DropDownList>
    </div>
    <div class="choice">
        <asp:Button ID="Button1" runat="server" Text="Vis utvalget"  />
    </div>
    <div class="choice">
        <asp:Button ID="Button2" runat="server" Text="Lag PDF" 
            onclick="Button2_Click"  />
    </div>
    <div class="choice">
        <asp:Label ID="Label1" runat="server" Text=" "></asp:Label>
    </div> 
    <div class="choice">
        <asp:Panel ID="Panel1" runat="server">
        <a href="output.pdf">PDF fil</a>
        </asp:Panel>    
    </div>        
    
</td>
<td valign="top" 
    style="border-left-style:solid; border-left-width:thin; padding-left:20px">
    <div>
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server" 
                     ChildrenAsTriggers="False" 
                     UpdateMode="Conditional" onload="UpdatePanel1_Load">
    <ContentTemplate>
    <div>
        <asp:Literal ID="Literal1" runat="server"></asp:Literal>
    </div>
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
    </Triggers>
    </asp:UpdatePanel>
    </div>   
</td>
</tr>
</table>
</form>
</body>
</html>

Fila er ganske rett fram. Merk at knappen med id Button1, er satt som trigger for oppdatering av UpdatePanel1. Vi kunne like godt ha laget en metode for klikk på knappen.

default.aspx.cs

Oppdatering av vinutvalget er slik:

protected void UpdatePanel1_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Literal1.Text = "<h3>Velg land og vintype</h3>";
        return;
    }       
    // fetch data
    String XmlSource =
            "http://www.ia.hiof.no/~borres/commondata/vin/viner.xml";
    // figure out what user has chosen
    String country = (String)DropDownListCountry.SelectedItem.ToString();
    String winetype = (String)DropDownListType.SelectedItem.ToString();
    // modify the selected string to match values on xml-file
    if (winetype.CompareTo("Musserende") == 0) winetype = "sparkling";
    else if (winetype.CompareTo("Rose") == 0) winetype = "rose";
    else if (winetype.CompareTo("Hvit") == 0) winetype = "white";
    else winetype = "red";
    // Access XML-file and perform transformation
    try
    {
        String physicalPath = 
            HttpContext.Current.Server.MapPath(".").ToString();
        // prepare the transformation
        XslCompiledTransform xslt = new XslCompiledTransform();
        xslt.Load(physicalPath + "\\App_Data\\tohtml_param.xslt");
        // set up an argumentlist with parameters
        XsltArgumentList argList = new XsltArgumentList();
        argList.AddParam("theCountry", "", country);
        argList.AddParam("theType", "", winetype);
        // Create a XmlWriter to stringbuffer 
        StringBuilder sb = new StringBuilder(4048);
        XmlWriter writer = XmlWriter.Create(sb);
        // Transform the file.
        xslt.Transform(XmlSource, argList, writer);
        writer.Flush();
        // pick relevant XML code as as text and display it
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(sb.ToString());
        String slist = doc.SelectSingleNode("//body").InnerXml;
        Literal1.Text = slist;
        writer.Close();
        // make a copy on disk for the pdf production
        XmlWriter fw = XmlWriter.Create(physicalPath + @"\output.html");
        doc.Save(fw);
        fw.Close();      
    }
    catch (Exception ex)
    {
        Literal1.Text = 
            String.Format(
                   "<div style=\"color:red\">Sorry, because: {0}</div>",
                   ex.Message);
    }
}

Vi kaller PrinceXML [1] for å lage PDF slik:

// make pdf
protected void Button2_Click(object sender, EventArgs e)
{
    String physicalPath =
            HttpContext.Current.Server.MapPath(".").ToString();
    // make pdf from the selected wines as saved in file
    string SOURCE_PATH = physicalPath + @"\output.html";
    string STYLE_PATH = physicalPath + @"\App_Data\report.css";       
    String ARGUMENTS = String.Format("{0} -s {1}", SOURCE_PATH, STYLE_PATH);
    String PRINCE_PATH;
    // are we running on server (donau)?
    Boolean isServer = physicalPath.IndexOf("wwwroot") != -1;
    if (isServer)
    {
        // 32-bit catalog on 64bit system on server
        PRINCE_PATH = 
            Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) +
            @"\Prince\Engine\bin\prince.exe";
    }
    else
    {
        // localhost and prince in Program Files
        //PRINCE_PATH = 
        //    Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) +
        //    @"\Prince\Engine\bin\prince.exe";
        
        // localhost and my prince catalog
        PRINCE_PATH = @"c:\fixed\Prince\Engine\bin\prince.exe";
    }
    
    Process PP = new Process();
    PP.StartInfo.UseShellExecute = false;
    PP.StartInfo.FileName = PRINCE_PATH;
    PP.StartInfo.Arguments = ARGUMENTS;
    PP.StartInfo.CreateNoWindow = true;
    try
    {
        PP.Start();
        PP.WaitForExit();
        Panel1.Visible = true;
    }
    catch (Exception ex)
    {
        Label1.Text = PP.StartInfo.FileName + " " + ARGUMENTS;
        Label1.Text += "  gives error: " + ex.Message;
        Panel1.Visible = false;
    }
    finally { 
        if (PP != null)
            PP.Close(); 
    }
}

Transformasjonen

Transformasjonen som foretar utvalger og formatterer som HTML, tohtml_param.xslt, er den samme som den som brukes i desktop applikasjonen, se XML og Vin:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output 
        method="xml" 
        encoding="ISO-8859-1"
         indent="yes" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
         doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
         media-type="text/xml"
         omit-xml-declaration="no"
         version="1.0"/>
  <!-- default values -->
  <xsl:param name="theCountry" select="'Frankrike'"/>
     <xsl:param name="theType" select="'red'"/>

    <xsl:template match="/">
        <html>
        <head>
            <title>Vinliste</title>
            <link rel="STYLESHEET" href="vin.css"/>
        </head>
        <body>
        <h1>Vinliste</h1>
        
        <xsl:variable name="list" 
                  select="//wine[country=$theCountry  and type=$theType]"/>
        
        <p>
        <xsl:value-of select="count($list)"/> viner
        </p>
      
        <hr/>
        <xsl:apply-templates select="$list">
            <xsl:sort select="type" order="ascending"/>
            <xsl:sort select="dice" order="descending"/>
            <xsl:sort select="price/volume" order="descending"/>
        </xsl:apply-templates>
        </body>
        </html>
    </xsl:template>

    <xsl:template match="//wine">
        <div class="wine">
        <div style="float:left">
        <xsl:element name="img">
            <xsl:attribute name="src"><xsl:value-of 
        select="type"/><xsl:value-of 
          select="dice"/>.gif</xsl:attribute>
            <xsl:attribute name="alt">dice</xsl:attribute>
        </xsl:element>
        </div>
        <div class="wine-name"><xsl:value-of select="name"/></div>
        <div class="wine-country"><xsl:value-of select="country"/></div>
        </div>
        <div style="clear:left"/>
        <div class="wine-desc"><xsl:value-of select="description"/></div>
        <div class="wine-price">
      NOK <xsl:value-of select="price"/> / <xsl:value-of select="volume"/>cl
    </div>
    </xsl:template>

</xsl:stylesheet>
Referanser
  1. Prince XMLPrincewww.princexml.com/14-03-2010
Eksempelet zippet: ajaxvin.zip
https://svn.hiof.no/svn/psource/Csharpsites/AjaxVin
En desktop versjon finner i modulen XML og Vin.
Vedlikehold

B. Stenseth, revidert mars 2010

(Velkommen) Moduler>AJAX>AJAX i .NET>Noen viner (Dokumentasjon)