views:

120

answers:

4

Hi all, first time poster. Please be gentle.

This topic may be similar to several other questions out there, but as far as I can see this is a unique problem I'm trying to solve. FWIW, I'm primarily a designer; I'm dangerous with Flash and HTML and CSS, but a bit in the weeds with everything else. From searching around, I appear to be heading for a ajax/jquery solution, which I need some help with.

To begin, I have built a fairly complex Flash interface which pulls content from a well-formed and validated XML file. This part is done, works beautifully.

However, the client wants to create a simple(r) javsScript version of the interface to be in place for viewers who don't have Flash. AND, they would like this version to pull values (text) from the SAME XML file, so they only need to edit the one file to make changes.

Seems like a reasonable request, but executing it doesn't appear to be quite so simple. The biggest hurdle is that I do not want to loop the XML for output - I want to call specific node values into specific elements.

Here's as simple an example as I can muster. From XML like so:

<section>
    <page>
        <name image="image1.jpg">Section One</name>
        <copy>This is a description of section one.</copy>
    </page>
    <page>
        <name image="image2.jpg">Section Two</name>
        <copy>This is a description of section two.</copy>
    </page>
</section>

I want to create HTML like so:

<div id="greenBackground">
    <h1>[value from 1st XML <name> node]</h1>
    <p>[value from 1st XML <copy> node]</p>
    <img src="[value from 1st XML <name> node image attribute]" />
</div>

<div id="blueBackground">
    <h1>[Value of 2nd XML <name> node]</h1>
    <p>[Value of 2nd XML <copy> node]</p>
    <img src="[value from 2nd XML <name> node image attribute]" />
</div>

They key is that each div has a different id, in order for each 'page' to have unique background colors and formatting. The idea is then that I would use a simple overlapping div script to show/hide each of these 'sections' within the same footprint.

Hopefully this makes sense, please don't hesitate for clarification. Any and all help is appreciated.

+6  A: 

Hi,

Sounds like you are trying to do a transformation from XML to HTML. For this you can use a technology called XSLT but commonly known by many as an xslt transformation. You can use xslt in conjunction with xpath (query language for xml) to do exactly what you describe in your question.

Here is the xml: (added the div id's to the xml)

<?xml version="1.0" encoding="utf-8"?>
<section>
    <page>
        <div id="greenBackground"></div>
        <name image="image1.jpg">Section One</name>
        <copy>This is a description of section one.</copy>
    </page>
    <page>
        <div id="blueBackground"></div>
        <name image="image2.jpg">Section Two</name>
        <copy>This is a description of section two.</copy>
    </page>
</section>

Here is the xslt:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:template match="/">
<html>
    <body>
        <xsl:for-each select="section/page">
        <div>
            <xsl:attribute name="id">
                <xsl:value-of select="div//@id"/>
            </xsl:attribute>
            <h1>
                <xsl:value-of select="name"/>
            </h1>
            <p>
                <xsl:value-of select="copy"/>
            </p>
            <img>
                <xsl:attribute name="src">
                    <xsl:value-of select="name//@image"/>
                </xsl:attribute>
            </img>
            </div>
        </xsl:for-each>
    </body>
</html>
</xsl:template>
</xsl:stylesheet>

Here is the output after you run the tranform:

<html>
  <body>
    <div id="greenBackground">
      <h1>Section One</h1>
      <p>This is a description of section one.</p><img src="image1.jpg"></div>
    <div id="blueBackground">
      <h1>Section Two</h1>
      <p>This is a description of section two.</p><img src="image2.jpg"></div>
  </body>
</html>

Enjoy!

Doug
+1 for using the technology that's designed to solve the problem, instead of forcing the technology you _want_ to use to fashion an ugly, non-intuitive, half-broken solution.
nearlymonolith
Thanks Doug. I'd actually already played with XLST and gotten some promising results, but didn't/don't know anything about xpath. Will check it out. Don't have enough rep or I'd give you +1.
OICJC
@Doug: your XSL looks mighty familiar to mine! :/
JohnB
@Doug - Thanks so much for the help. Between your answer and the others below (which are remarkably similar, telling me this is the right way to go!), I've got the XML formatting beautifully with an XSL file. The only part I'm missing is how to bring the XLS-transformed XML into my HTML page with the overlapping div script. Maybe that should be a separate question?
OICJC
Can you clarify what problem you are experiencing? Sounds like you are doing the xsl transform and have the resultant html - are you doing the transform outside of the page? What technology are you using - straight html, php, asp, asp.net
Doug
@Doug - I think I don't understand how to 'do' the transform. I have my XSL file, and my XML file which links to the XSL. And when I preview the XML file it appears formatted and with the HTML structure I want. Now, how do I pull that HTML into the containing page, with the Flash movie and the jS controls to overlap/switch divs? Remember, I am trying to use the same (external) XML file to serve two purposes. I am probably missing something very simple. And currently I'm working in straight HTML w/jS.
OICJC
+1  A: 

Change your XML to this (to set the div id names):

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="web_page.xsl"?>
<section>
  <page>
    <div_id>greenBackground</div_id>
    <name image="image1.jpg">Section One</name>
    <copy>This is a description of section one.</copy>
  </page>
  <page>
    <div_id>blueBackground</div_id>
    <name image="image2.jpg">Section Two</name>
    <copy>This is a description of section two.</copy>
 </page>

This XSL will translate your XML just the way you asked:

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

<xsl:template match="/">
  <html>
  <body>
    <xsl:for-each select="section/page">
    <div>
      <xsl:attribute name="id">
        <xsl:value-of select="div_id"/>
      </xsl:attribute>
      <h1><xsl:value-of select="name"/></h1>
      <p><xsl:value-of select="copy"/></p>
      <img>
        <xsl:attribute name="src">
          <xsl:value-of select="name//@image"/>
        </xsl:attribute>
      </img>
    </div>
  </xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
JohnB
@JohnB - Thanks for also answering. Your XSL does look remarkably similar to @Doug's, above, but two nearly identical answers makes me think they're both on the money.
OICJC
Ha Ha it might have something to do with the fact JohnB sits next to me in the office ;)
Doug
+4  A: 

Here's another version. I find it much cleaner if you:

  • avoid <xsl:for-each/> (using XSLT's pattern matching instead is more idiomatic)
  • use attribute value templates (these are the attribute="{..}")
  • you should also set <xsl:output/> since you're generating HTML (I have assumed 4.0)

I assume you can add an extra attribute id on your <page/> elements in the input (otherwise there's nowhere to get your id from!)

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

<xsl:template match="/">
    <html>
        <body><xsl:apply-templates/></body>
    </html>
</xsl:template>

<xsl:template match="page">
    <div id="{@id}">
        <h1><xsl:value-of select="name"/></h1>
        <p><xsl:value-of select="copy"/></p>
        <img src="{name/@image}"/>
    </div>
</xsl:template>

</xsl:stylesheet>
Porges
Thanks for the answer, Porges. I'll try this version out as well.
OICJC
+1  A: 

This is how to get the transformation done with PHP:

$proc=new XsltProcessor;  
$proc->importStylesheet(DOMDocument::load("stylesheet.xsl"));  
echo $proc->transformToXML(DOMDocument::load("data.xml"));  
Andreas