1

I need to display data ("document" and "manual" XML elements) from XML file into GridView control as a link. The only way that works for me is using CDATA section (I used it for "document" element below). But I need to find a way to avoid using CDATA to make .xml file simpler. It should allow me to make a link as a string in code behind file and leave just the name of the document in .xml file. I tried another way with "manual" element (using XmlNode). But the problem is that it display the same links in all the cells of GridView (because it takes "manual" elements from all the XML document) but it should be different for each row.

Please see my .xml file, .cs file and .aspx page below.

XML file:

<?xml version="1.0" encoding="utf-8" ?>
<document_topics>
  <release id="936896294">
    <topic>
      <name>
        Account Connect
      </name>
      <document>
        <![CDATA[<a href="DocumentLocator.aspx?dn=AT100000&r=936896294">AT100000</a><br>
      <a href="DocumentLocator.aspx?dn=AT100010&r=936896294">AT100010</a><br>
      <a href="DocumentLocator.aspx?dn=AT100020&r=936896294">AT100020</a><br>
      <a href="DocumentLocator.aspx?dn=AT100030&r=936896294">AT100030</a><br>
      <a href="DocumentLocator.aspx?dn=AT100040&r=936896294">AT100040</a>]]>
      </document>
      <manual>
        RR320000
      </manual>
      <project>
      </project>
    </topic>
    <topic>
      <name>
        Bankruptcy Proof of Claim
      </name>
      <document>
        <![CDATA[<a href="DocumentLocator.aspx?dn=PM400692&r=936896294">PM400692</a><br>
      <a href="DocumentLocator.aspx?dn=RP1212001&r=936896294">RP1212001</a><br>
      <a href="DocumentLocator.aspx?dn=RP1212002&r=936896294">RP1212002</a><br>
      <a href="DocumentLocator.aspx?dn=SP027POCF&r=936896294">SP027POCF</a><br>
      <a href="DocumentLocator.aspx?dn=SP027POCL&r=936896294">SP027POCL</a><br>]]>
      </document>
      <manual>
        TR320010
      </manual>
      <manual>
        TR320020
      </manual>
      <project>
        PD55588
      </project>
      <project>
        PD23459
      </project>
    </topic>
  </release>
</document_topics>

`

.aspx page (part with GridView code):

<asp:GridView ID="gvDocumentTopics" SkinID="MainGrid" EmptyDataText="No Results" Width="100%" runat="server">
<Columns>
    <asp:TemplateField ItemStyle-Width="25%" HeaderText="Topic">
        <ItemTemplate>
            <%# XPath("name").ToString() %>
        </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField ItemStyle-Width="25%" HeaderText="Document Reference">
        <ItemTemplate>
            <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="" Text='<%# XPath("document").ToString() %>'></asp:HyperLink>
        </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField ItemStyle-Width="25%" HeaderText="Manual Reference">
        <ItemTemplate>
            <%foreach (var link in links)
                {%>
            <%=link%><br />
            <%}%>
        </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField ItemStyle-Width="25%" HeaderText="Related Project">
        <ItemTemplate>
            <%# XPath("project").ToString() %>
        </ItemTemplate>
    </asp:TemplateField>
</Columns>

I used C# for reading XML.

using Latitude.Web.Helpers;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;

namespace Latitude.Web
{
    public partial class Index : System.Web.UI.Page
    {
        public List<string> links = new List<string>();
        public string link;
        public string relId;

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Request.QueryString["relId"] != null)
            {
                relId = ValidationHelper.ValidateReleaseIdString(Request.QueryString["relId"], ExceptionHelper.GetValidReleaseException(Request.QueryString["relId"]));
                XmlDataSource1.DataFile = Server.MapPath("~/App_Data/IndexItems.xml");
                XmlDataSource1.XPath = "document_topics/release[@id='" + relId + "']/topic";
                XmlDataSource1.DataBind();

                gvDocumentTopics.DataSource = XmlDataSource1;
                gvDocumentTopics.DataBind();

                XmlDocument doc = new XmlDocument();
                doc.Load(Server.MapPath("~/App_Data/IndexItems.xml"));

                XmlNodeList manualsXML = doc.SelectNodes("document_topics/release[@id='" + relId + "']/topic/manual");

                foreach (XmlNode xNode in manualsXML)
                {
                    string manual = xNode.InnerText;

                    if (!String.IsNullOrEmpty(manual))
                    {
                        string link = String.Format("<a href=\"DocumentLocator.aspx?dn={0}&r={1}\">{0}</a>", manual, relId);
                        links.Add(link);
                    }
                }
            }
        }
    }
}
mxmissile
  • 11,464
  • 3
  • 53
  • 79
Tanya K.
  • 29
  • 4
  • Welcome to StackOverflow! Your question is way to long, please see how to create a [mcve]. – Hille Oct 08 '19 at 14:59
  • *"I need to find a way to avoid using CDATA"* - using XHTML is one way to accomplish this. Right now, it doesn't validate as XHTML (and therefore XML) because `
    ` is not closed and `&` is not escaped in the `href` attribute. From there, use your own XML structure that doesn't repeat anything that doesn't change. If you need HTML at some point, reconstitute it from your XML structure.
    – madreflection Oct 08 '19 at 15:15

1 Answers1

0

I put results into a datatable. You can modify and put into any object

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Linq;
using System.Data;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Topic Name", typeof(string));
            dt.Columns.Add("Manual", typeof(string));
            dt.Columns.Add("Project", typeof(string));
            dt.Columns.Add("Document", typeof(string));
            dt.Columns.Add("HREF", typeof(string));

            XDocument doc = XDocument.Load(FILENAME);
            string pattern = "href=\"(?'href'[^\"]+)\">(?'innertext'[^<]+)";
            foreach (XElement topic in doc.Descendants("topic"))
            {
                string name = (string)topic.Element("name");
                string manual = string.Join(",", topic.Elements("manual").Select(x => ((string)x).Trim()));
                string project = string.Join(",",topic.Elements("project").Select(x => ((string)x).Trim()));

                XElement document = topic.Element("document");

                string items = document.Value;
                MatchCollection matches = Regex.Matches(items, pattern);
                foreach (Match match in matches)
                {
                    dt.Rows.Add(new object[] {
                        name,
                        manual,
                        project,
                        match.Groups["innertext"].Value,
                        match.Groups["href"].Value
                    });
                }
            }
        }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • Thank you a lot for your answer!I tried your solution. But I need to display all links for each topic in ONE cell. I don't need to display each link in a separate row. Do you have any idea how to achieve that? I was thinking about using datatable inside the row, but I stuck at the implementation... – Tanya K. Oct 08 '19 at 16:21
  • See following : https://stackoverflow.com/questions/37752266/how-to-merge-multiple-columns-values-into-one-column-asp-net-gridview-c-sharp rorhttps://stackoverflow.com/questions/16147963/gridview-with-merged-cells – jdweng Oct 08 '19 at 16:27