tags:

views:

106

answers:

3

Hi everyone.

I'm writing a dummy "MyAgenda" application in Java which has to allow maintenance of the XML file that stores the data.

Say I have a XML file like:

<myagenda>
  <contact>
    <name>Matthew Blake</name>
    <phone>12345678</phone>
  </contact>
</myagenda>

How can I add a new <contact> by using XSLT ?

Thanks.

+1  A: 

XSLT converts 1 xml file to another xml or text file.

Rohit
Is it possible to automatically replace the old file with the resulting one directly from XSLT script, not from Java ?
mat
@Rohit is right. Besides, the source and target files are technically outside of the scope of the XSLT processor. The path to save the document must be set in Java in your case.
Eric Bréchemier
+3  A: 

use the xsl:param as a global parameter in the header of your xsl stylesheet.

<xsl:param name="newname"/>
<xsl:param name="newphone"/>

fill the new params with your xslt engine and then add the new item via a template:

(...)
<xsl:template match="myagenda">

<xsl:apply-templates select="contact"/>

<xsl:if test="string-length($newname)&gt;0">
 <xsl:element name="contact">
  <xsl:element name="name">
    <xsl:value-of select="$newname"/>
  </xsl:element>
  <xsl:element name="phone">
    <xsl:value-of select="$newphone"/>
  </xsl:element>
 </xsl:element>
</xsl:if>
</xsl:template>
(...)
Pierre
This will work for the example provided. But it makes assumptions about the structure of the input XML that it really doesn't need to and that could be quite harmful - it will strip attributes, comments, processing instructions, and child elements that aren't named `contact` from the input `myagenda` element. Also, while using `xsl:element` certainly works, it's almost always unnecessary if you're not programmatically generating the name of the element, which you're not in this case.
Robert Rossney
its the perfect answer .. yes you can pass the params(parameters) to the XSLT file .. by calling program (C#, java or whichever) .. You can use that variable wherever you wish to ..
infant programmer
+3  A: 

Start with the identity transform, which transforms any XML document into itself.

The identity transform is a simple machine: given a tree, it copies every node it finds recursively. You're going to override its behavior for one specific node - the myagenda element - which it's going to copy in a different way.

To do this, add a template that matches the element that you want to update and duplicates it. In your case:

<xsl:template match="myagenda">
  <xsl:copy-of select=".">
     <xsl:apply-templates select="node() | @*"/>
  </xsl:copy-of>
</xsl:template>

You might think, "wait isn't that the identity transform?" It is, but it's not going to stay that way.

Now decide on how you're going to get the new contact information into the transform. There are basically two ways: read it from a separate XML document using the document function, or pass the values into the transform using parameters. Let's assume that you're using parameters; in this case, you'd add the following to the top of your XSLT (right after the xsl:output element):

<xsl:param name="contactName"/>
<xsl:param name="contactPhone"/>

Now, instead of transforming myagenda into a copy of itself, you want to transform it into a copy of itself that has a new contact in it. So modify the template to do this:

<xsl:template match="myagenda">
  <xsl:copy-of select=".">
     <xsl:apply-templates select="node() | @*"/>
     <contact>
        <name><xsl:value-of select="$contactName"/></name>
        <phone><xsl:value-of select="$contactPhone"/></phone>
     </contact>
  </xsl:copy-of>
</xsl:template>

If you wanted to get the name and phone out of a separate XML document in the file system, you'd start the XSLT with something like this:

<xsl:variable name="contact" value="document('contact.xml')"/>
<xsl:variable name="contactName" value="$contact/*/name[1]'/>
<xsl:variable name="contactPhone" value=$contact/*/phone[1]'>

That reads in contact.xml and finds the first name and phone element under the top-level element (using * in the pattern means that you don't care what the top-level element's name is).

Robert Rossney