Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old January 20th, 2008, 07:40 PM
Registered User
 
Join Date: Jan 2008
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default Printing nodes as they appear in the XML

Hello all,
I've not entirely new to XML and XSL but I'm working on a new project that's s got me a bit perplexed. What I'm looking at doing is printing out the contents of each node based on the order they are in in the XML. I'm doing some simple tests to start out with and the XML I'm working with is
<script>
<screenplay>
<character>Character1</character>
<dialogue>here is dialogue</dialogue>
<character>Character2</character>
<dialogue>here is more dialogue</dialogue>
</screenplay>
</script>

What I'd like to do is print out first character name, their dialogue then the next character name and their dialogue. I was thinking of using a for-each loop and using an if statement to check the node name of the current node in order to properly format the contents. I partially have that working but I'm not sure how to grab the name of the current node.

I was also playing with apply-templates but that would print all characters first and then print all the dialogue together which isn't what I'm looking for.

Thanks in advance for any help.


 
Old January 20th, 2008, 08:58 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You haven't said what output you want. The only case that's a little difficult is you need output in the form

<speech>
  <character>...</character>
  <dialogue>...</dialogue>
</speech>
<speech>
  <character>...</character>
  <dialogue>...</dialogue>
</speech>

which is probably how the XML should have been designed in the first place (except that your dialogue is really a monologue, right?) The best way of achieving this is probably

<xsl:for-each select="character">
  <speech>
     <xsl:copy-of select="."/>
     <xsl:copy-of select="following-sibling::dialogue[1]"/>
  </speech>
</xsl:for-each>

(or the equivalent using apply-templates).

If a character can be followed by several dialogue elements then you have a classic positional grouping problem, best solved using xsl:for-each-group in XSLT 2.0 or by sibling recursion in XSLT 1.0

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old January 20th, 2008, 11:00 PM
Registered User
 
Join Date: Jan 2008
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

My output is going to be text and the node type will determine the formatting (ie will it be in all caps or not, how much is it going to be indented, justification etc)

To take this scenario one step farther, I will eventually have other nodes in there like scene, shot, transition and a couple others which will be in between the dialogue. Will this example work with that as well? I'm going to use the example shown, get that working and go from there to see what I can come up with.

[EDIT]
I did some more playing around and I think I've found the answer. The XML is now
Code:
<script>
<screenplay>
<scene name="this is a scene">
<character>Dana</character>
<parenthetical>excited</parenthetical>
<dialogue>here is dialogue</dialogue>
<character>David</character>
<parenthetical>sleepily</parenthetical>
<dialogue>here is David's dialogue</dialogue></scene>
</screenplay>
</script>
 and my xsl is:
Code:
<stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform">
  <output method="text" indent="yes"/>
  <variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
  <variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

  <template match="script/screenplay/scene">
    <value-of select="translate(@name, $smallcase, $uppercase)"/>
    <text>#xd;#xa;</text><text>#xd;#xa;</text>
    <for-each select="child::node()">
   <if test="name(current())='character'">
      <value-of select="translate(current(), $smallcase, $uppercase)"/><text>#xd;#xa;</text></if>
    <if test="name(current())='dialogue'"><value-of select="current()"/><text>#xd;#xa;</text><text>#xd;#xa;</text>
    </if>
    <if test="name(current())='parenthetical'">(<value-of select="current()"/>)<text>#xd;#xa;</text></if>
    </for-each>
  </template> 
</stylesheet>
Obviously I have more formatting that needs to be done but that part should be easy. :)
 
Old January 21st, 2008, 05:43 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

This works just as well, avoids lots of <if> and name() calculations and is much easier to read. It is also more 'xslt'-like, using the language as it was designed to be used.

<template match="script/screenplay/scene">
<value-of select="translate(@name, $smallcase, $uppercase)"/>
<text>#xd;#xa;</text><text>#xd;#xa;</text>
<apply-templates select="*"/>
</template>

<template match="character">
  <value-of select="translate(., $smallcase, $uppercase)"/><text>#xd;#xa;</text>
</template>

<template match="dialogue">
  <value-of select="."/><text>#xd;#xa;</text><text>#xd;#xa;</text>
</template>

<template match="parenthetical">
  (<value-of select="."/>)<text>#xd;#xa;</text>
</template>


/- Sam Judson : Wrox Technical Editor -/
 
Old January 21st, 2008, 05:50 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

Oh, and if you are using XSLT 2.0 then the upper-case() function would be a much better replacement for the translate code you are using.

/- Sam Judson : Wrox Technical Editor -/





Similar Threads
Thread Thread Starter Forum Replies Last Post
XML + XSLT Compare Nodes tommyready XSLT 5 September 5th, 2007 03:18 AM
Recursive nodes in XML Schema XSLTer XML 1 April 13th, 2007 12:25 PM
I cant retrieve XMl child nodes jfergy Classic ASP XML 0 December 8th, 2006 10:24 PM
Copying XML nodes from one document to another hughcr C# 2 May 12th, 2005 01:20 AM
Display nodes from xml nambati XSLT 2 September 17th, 2004 07:57 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.