tags:

views:

132

answers:

4

FIRST EDIT
I'm fetching the Child 1 tag into a DropDownList in a C# form, Plz suggest the best practise code (C#) for deleting the Parent tag & all it's child tags in an XML file. Example:

    <Parents>
      <Parent>
        <Child 1>Something</Child 1>
        <Child 2>Something</Child 2>
        <Child 3>Something</Child 3>
        <Child 4>Something</Child 4>
      </Parent>
      <Parent>
        <Child 1>Something 1</Child 1>
        <Child 2>Something 1</Child 2>
        <Child 3>Something 1</Child 3>
        <Child 4>Something 1</Child 4>
      </Parent>
    </Parents>

--- Previous Question ---
How can I insert the following stylesheet tag into my new xml file which is created using C# code????

<?xml-stylesheet type="text/xsl" href="issuez.xsl"?>

C# code to create the xml file:-

new XDocument(
                        new XElement("issues",
                            new XElement("issue",
                            new XElement("cat", comboBox1.Text),
                            new XElement("desc", richTextBox1.Text),
                            new XElement("end", dateTimePicker1.Text),
                            new XElement("att", textBox2.Text)
                            )
                        )
                        ).Save(path);
+2  A: 

This is the sort of thing that the back end producing the XML should handle. XSLT isn't the best place for lots of logic. Better to embed all that in the XML after you query for the news items. Just send them to the client in the proper form so they don't have to work so hard.

duffymo
an u please explain this with a piece of code for C#???
gsvirdi
This is precisely what XSLT was designed for.
Robert Rossney
I disagree. XSLT is for transforming XML from one form to another, but if your stylesheet starts having too much logic in it I'd argue that it may be misplaced. XSLT certainly can do it; I just don't think it's always the best place for it. And I certainly don't want clients to have to do a lot of work.
duffymo
You think building a key and using it is too much logic?
Robert Rossney
Not sure what "building a key" means, but if you're saying that the source of the XML should build in an element that allows XSTL to render with a simple <choose>, then I'm in favor. I'm simply against turning XSTL into a scripting language.
duffymo
A: 

If you use the XSLT processor from PHP, you can use PHP-functions inside your XSLT script. All you need is call registerPhpFunctions before transformation. The result value in the right order can be used for sorting.

Andreas
I'm sorry.... I was using Windows Forms (C#) and xml to present the output to the user. Any help please????
gsvirdi
I'm not familiar with this. For hints solving the problem with XSLT look at http://www.jenitennison.com/xslt/grouping/index.xml
Andreas
+1  A: 

An XSLT stylesheet allows global parameters that can be set before a transformation is run. So with XSLT 1.0 and .NET's XslCompiledTransform if you need the current date in your stylesheet you can define a global parameter

  <xsl:param name="current-date"/>

and set that before running the transformation by creating an XsltArgumentList, setting the parameter to a value and format you want/need and then pass that XsltArgumentList as the second argument to the Transform method. Then in your stylesheet you can compare the date in an XML input element or attribute to the parameter.

As you use .NET a different option is to use XSLT 2.0; Microsoft does not support that but with Saxon 9 there is a third party solution. XSLT/XPath 2.0 have a function named current-date, that way you don't need a parameter.

Martin Honnen
+3  A: 

First, make sure that dates in your XML are represented in the canonical YYYY-MM-DD format, and times as HH:MM:SS, so that XSLT (which, in 1.0, doesn't have date or time datatypes) can compare and sort them.

Second, use Steve Muench's technique for grouping. You generate a key on the items' dates, using xsl:key. The key() function can then be used to find a list of all items on a given date.

Using that key, you can build a list of the distinct dates that appear in the items. This is the Muenchian technique: find each item that's the first item in the list that key() returns for that item's date. This technique guarantees that you're always get one and only one item for each distinct date value. You then sort those items, and use their dates to drive the actual production of your output.

A minimal example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

  <xsl:key name="dates" match="/data/newsitem" use="@date"/>

  <xsl:template match="/">
    <output>
      <!-- find exactly one newsitem node for each distinct @date in the document -->
      <xsl:for-each select="/data/newsitem[generate-id() = generate-id(key('dates', @date)[1])]">
        <xsl:sort select="@date" order="descending"/>
        <xsl:call-template name="newsitems_for_date">
          <xsl:with-param name="date" select="@date"/>
        </xsl:call-template>
      </xsl:for-each>
    </output>
  </xsl:template>

  <xsl:template name="newsitems_for_date">
    <xsl:param name="date"/>
    <h1>
      <xsl:value-of select="$date"/>
    </h1>
    <xsl:apply-templates select="/data/newsitem[@date=$date]">
       <xsl:sort select="@time" order="descending"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="newsitem">
    <p>
      newsitem for <xsl:value-of select="@date"/>
    </p>
  </xsl:template>

</xsl:stylesheet>
Robert Rossney
Good explanation of Muenchian grouping, but why not use the key when extracting newsitems for a given date, i.e. replace `/data/newsitem[@date=$date]` with `key('dates', $date)`?Also, using `count(.|key('dates', $date)[1]) = 1` instead of `generate-id() = generate-id(key('dates', @date)[1])` might yield better performance, as described on http://www.tkachenko.com/blog/archives/000401.html.Finally, Muenchian grouping is only needed with XSLT 1.0. With XSLT 2.0, use `xsl:for-each-group` instead.
markusk
In my previous comment, it should be `count(.|key('dates', @date)[1]) = 1`, not `count(.|key('dates', $date)[1]) = 1`.
markusk
It didn't occur to me that you could sort the results of `key()`, but of course you can.
Robert Rossney