1

I have a XML file which has non standard html elements like so: Note: Paragraphs have been shortend.

                 <content>
                      Sacrifice. It's Mass Effect 3's major theme...
                      <p />
                      Mass Effect was about time and place; you d...
                      <p />
                      Mass Effect 3 is focused more on plot th...
                      <p />
                      <img url="me3_img1.jpg">Plenty of games feat...</img>
                      Like Star Wars, Mass Effect 3 is an inc...
                      <p />
                      The reapers aren't your only adver...
                      <p />
                      <img url="me3_img2.jpg">If looks could kill..</img>
                      The series' focus on player choice is as vi...
                      <p />
                      This intense narrative is met wi...
                      <p />
                      <img url="me3_img3.jpg">The sun is sett...</img>
                      These are exquis...
                 </content>

Each will be a gap between the paragraphs. Each image must appear in-between paragraphs where they apear in the content, the must also have a caption, with the content being that between and Note also that the has a url and not a src, so this must change.

My current xslt only copy-of, and css fixes the layout, but img are not displaying because I can't change url to src, aswell as set the caption.

Please help.

Update:

<xsl:for-each select='./review/content/child::*'>
                          <xsl:value-of select="name()"/>
                          <xsl:choose>
                            <xsl:when test="name()='p'">
                              <p />
                            </xsl:when>
                            <xsl:when test="name()='img'">
                              <div class="reviewImage">
                                <img>
                                  <xsl:attribute name="src">
                                    <xsl:value-of select="./@url"/>
                                  </xsl:attribute>
                                </img>
                                <xsl:value-of select="."/>
                              </div>                                
                            </xsl:when>
                            <xsl:otherwise>
                              <xsl:value-of select="."/>
                            </xsl:otherwise>
                          </xsl:choose>
                        </xsl:for-each>

It is not outputing any of the text(). The Images and captions are sorted now though.

Solution found:

                       <xsl:for-each select='./review/content/node()'>
                          <xsl:choose>
                            <xsl:when test="name()='p'">
                              <p />
                            </xsl:when>
                            <xsl:when test="name()='img'">
                              <div class="reviewImage">
                                <img>
                                  <xsl:attribute name="src">
                                    <xsl:value-of select="./@url"/>
                                  </xsl:attribute>
                                </img>
                                <xsl:value-of select="."/>
                              </div>                                
                            </xsl:when>
                            <xsl:otherwise>
                              <xsl:value-of select="."/>
                            </xsl:otherwise>
                          </xsl:choose>
                        </xsl:for-each>

2 Answers 2

1

When you want to copy something and change part of it, the answer is almost always to use the identity template with additional templates. copy-of cannot do this, and I avoid copy-of as much as I can.

Here is how you can do what you describe (when you say "caption", I'm not sure whether you mean alt or title attributes, so I'll use both:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

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

  <xsl:template match="content/img">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:attribute name="alt">
        <xsl:value-of select="."/>
      </xsl:attribute>
      <xsl:attribute name="title">
        <xsl:value-of select="."/>
      </xsl:attribute>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="content/img/@url">
    <xsl:attribute name="src">
      <xsl:value-of select="." />
    </xsl:attribute>
   </xsl:template>
</xsl:stylesheet>

When this is run on your sample input, the result is:

<content>
  Sacrifice. It's Mass Effect 3's major theme...
  <p />
  Mass Effect was about time and place; you d...
  <p />
  Mass Effect 3 is focused more on plot th...
  <p />
  <img src="me3_img1.jpg" alt="Plenty of games feat..." title="Plenty of games feat..." />
  Like Star Wars, Mass Effect 3 is an inc...
  <p />
  The reapers aren't your only adver...
  <p />
  <img src="me3_img2.jpg" alt="If looks could kill.." title="If looks could kill.." />
  The series' focus on player choice is as vi...
  <p />
  This intense narrative is met wi...
  <p />
  <img src="me3_img3.jpg" alt="The sun is sett..." title="The sun is sett..." />
  These are exquis...
</content>
1
  • The url is not changed yet to src.
    – Gerardlamo
    Commented May 19, 2013 at 14:24
0

The point of copy-of is to copy content unchanged from the input tree to the output tree.

In order to change something between the input and output trees, you will want to use apply-templates and template.

If you wish to output an element on the output tree with the same name as on the input tree, but different content, you can use copy in your template, and fill the "copy" with the appropriate content.

3
  • How would I then split the <p /> or even keep track of where each image belongs?
    – Gerardlamo
    Commented May 19, 2013 at 12:11
  • I'm not sure what you mean by "split the p", copy-of won't do that either, but you would probably do that with a template that matches p and "splits" it. Commented May 19, 2013 at 12:43
  • You don't need to keep track of where the images belong. By default, apply-templates operates on the selected nodeset in document order, so that will just happen. Commented May 19, 2013 at 12:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.