3

I have this XML file:

<questions>
  <question id="title">
    <option>
      <text>Mr</text>
      <value>Mr</value>
    </option>
    <option>
      <text>Ms</text>
      <value>Ms</value>
    </option>
  </question>
  <question id="organisation">
    <option>
      <text>org1</text>
      <value>org1</value>
    </option>
    <option>
      <text>org2</text>
      <value>org2</value>
    </option>
  </question>
</questions>

How do I bind each question to a specific drop-down in c#?

Thanks

3 Answers 3

2

You could use a XmlDataSource. Because your XML is not conform to what this control expects you will need to adapt it by using a XSL transformation.

So Step 1:

Define a XSL transformation (~/App_Data/questions.xslt):

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="questions">
    <questions>
      <xsl:apply-templates select="question"/>
    </questions>
  </xsl:template>
  <xsl:template match="option">
    <option>
      <xsl:attribute name="text">
        <xsl:value-of select="text"/>
      </xsl:attribute>
      <xsl:attribute name="value">
        <xsl:value-of select="value"/>
      </xsl:attribute>
    </option>
  </xsl:template>
</xsl:stylesheet>

Step 2:

Use it:

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="Form1" runat="server">
        <asp:DropDownList 
            ID="ddl" 
            runat="server" 
            DataSourceID="ds" 
            DataTextField="text" 
            DataValueField="value" 
        />

        <asp:XmlDataSource 
            ID="ds" 
            runat="server" 
            DataFile="~/App_Data/questions.xml" 
            TransformFile="~/App_Data/questions.xslt" 
            XPath="//option" 
        />
    </form>
</body>
</html>

Notice how the TransformFile property on the data source is pointing to the XSL file.

Sign up to request clarification or add additional context in comments.

4 Comments

the format of the XML is not fixed. Is there a different format that woudn't need the XSL transformation?
Yes, it's the one produced by the XSL transformation. If it is not fixed you will need to fix it or you can't use it. Another possibility would be to generate this XSL file dynamically based on the syntax of your XML file but I would really recommend you normalizing it.
ok so what would be the XPath to match only the values under: question id="title"
Xpath would be: /Question[id="title"]/Option. One thing to note for the XmlDataSource is that caching is enabled by default which could cause you some headaches. I usually turn it off i.e. EnableCache="False".
0

You could use the XmlDataSource class to bind the XML data to your control.

Comments

0

You can use XDocument

string xml = ""; /* your xml */
XDocument xDocument = XDocument.Parse(xml);
foreach(XElement questionElement in xDocument.Root.Elements("question"))
{
 foreach(XElement optionElement in questionElement.Elements("option"))
 {
  string text = optionElement.Element("text").Value;
  string value = optionElement.Element("value").Value;
  /* do something with them here */
 }
}

Using the attribute id to bind all select boxes:

string xml = ""; /* your xml */
XDocument xDocument = XDocument.Parse(xml);
foreach(XElement questionElement in xDocument.Root.Elements("question"))
{
 string id = questionElement.Attribute("id").Value;
 foreach(XElement optionElement in questionElement.Elements("option"))
 {
   string text = optionElement.Element("text").Value;
   string value = optionElement.Element("value").Value;
   /* bind selectbox options here, using id,text,value */
 }
}

Using id to bind one select box:

string id = "title";  
string xml = ""; /* your xml */
XDocument xDocument = XDocument.Parse(xml);  
XElement questionElement = xDocument.Root.Elements("question").SingleOrDefault(e => e.Attribute("id").Value == "title");
if (questionElement != null)
{
 foreach(XElement optionElement in questionElement.Elements("option"))
 {
  string text = optionElement.Element("text").Value;
  string value = optionElement.Element("value").Value;
  /* bind selectbox options here, using id,text,value */
 }
}

3 Comments

thanks. how would you match only the nodes of a specific question, ie. question id="title"?
xDocument.Elements("question").Where(e => e.Attribute("id").Value == "title"); will do that. You'll probably have to add some Exception catching for the situation when the id attribute does not exist though. Also consider the new piece of code that I posted.
I like this approach but rather than looping and adding items to the List (which you'd have to do on each postback) you could DataBind the list to a collection of anonymous types.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.