Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Replace text() elements with <p> tekst <p> 1

Status
Not open for further replies.

Gert74

Technical User
Jan 26, 2001
48
0
0
NL
Hi all,

I have the following problem. I have an XML file like below. I want to output this as valid xhtml (with xslt) and therefore all text-elements without an html-tag should be surrounded by a paragraph-tag. Although I'm pretty sure that it's relatively easy, but I don't know how to do it.

XML:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<content>
	And here a text without surrounding paragraph-element
	<p>Deze alinea heeft volgordenummer 20, maar daar zie je&nbsp;<a href="tcm:17-58812" xmlns:xlink="[URL unfurl="true"]http://www.w3.org/1999/xlink"[/URL] xlink:title="Nu" tcmuri="tcm:17-58812">straks</a> niets meer van. Wel zou deze dan ook op de tweede plek in het component moet staan,&nbsp;<strong>terwijl</strong> deze als eerste is ingevoerd. Hierbij trouwens een&nbsp;<A href="tcm:17-58769" xmlns:xlink="[URL unfurl="true"]http://www.w3.org/1999/xlink"[/URL] xlink:title="Test algemeen" tcmuri="tcm:17-58769">link</A> naar een andere component.</p>
	<p>Bijgevoegd de&nbsp;<a href="tcm:17-58804" xmlns:xlink="[URL unfurl="true"]http://www.w3.org/1999/xlink"[/URL] xlink:title="blabla SP3 ReleaseNotes" tcmuri="tcm:17-58804">Blablabla SP3 ReleaseNotes</a></p>
	And another text without paragraph-elemen
	<ul>
		<li>item 1</li>
		<li>item 2</li>
	</ul>
</content>

Output should be like this:
Code:
	<p>And here a text without surrounding paragraph-element</p>
	<p>Deze alinea heeft volgordenummer 20, maar daar zie je&nbsp;<a href="tcm:17-58812" xmlns:xlink="[URL unfurl="true"]http://www.w3.org/1999/xlink"[/URL] xlink:title="Nu" tcmuri="tcm:17-58812">straks</a> niets meer van. Wel zou deze dan ook op de tweede plek in het component moet staan,&nbsp;<strong>terwijl</strong> deze als eerste is ingevoerd. Hierbij trouwens een&nbsp;<A href="tcm:17-58769" xmlns:xlink="[URL unfurl="true"]http://www.w3.org/1999/xlink"[/URL] xlink:title="Test algemeen" tcmuri="tcm:17-58769">link</A> naar een andere component.</p>
	<p>Bijgevoegd de&nbsp;<a href="tcm:17-58804" xmlns:xlink="[URL unfurl="true"]http://www.w3.org/1999/xlink"[/URL] xlink:title="blabla SP3 ReleaseNotes" tcmuri="tcm:17-58804">Blablabla SP3 ReleaseNotes</a></p>
	<p>And another text without paragraph-elemen</p>
	<ul>
		<li>item 1</li>
		<li>item 2</li>
	</ul>

Gert
 
This is not valid XML. &nbsp; is not a valid entity. Change it to &#160; (or &#xA0;). XSL can only deal with valid XML. Then use this XSL:
Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
  <xsl:output method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>[/URL]
  <xsl:template match="/">
    <html>
      <head>
        <title>XHTML Page</title>
      </head>
      <body>
        <xsl:apply-templates select="content"/>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="content">
    <xsl:apply-templates select="*|text()"/>
  </xsl:template>
  <xsl:template match="@*|node()">
    <xsl:copy-of select="."/>
  </xsl:template>
  <xsl:template match="text()">
    <p><xsl:value-of select="."/></p>
  </xsl:template>
</xsl:stylesheet>

Jon

"Asteroids do not concern me, Admiral. I want that ship, not excuses.
 
After implementing the suggested solution I discovered a new problem. Editors are allowed to enter elements like <strong> or <a> etcetera. If they do that my output looks like this:
Code:
<p>Hallo wereld ik ben</p><strong>vetgedrukt</strong><p>. En ik dan weer niet. </p>
<p>Dit is een mooie tekst  gebruik van leestekens is er natuurlijk niets aan de hand. Kijken wat er nu gebeurt.</p>

Of course I don't want it that way, but this way:
Code:
<p>Hallo wereld ik ben <strong>vetgedrukt</strong>. En ik dan weer niet. </p>
<p>Dit is een mooie tekst  gebruik van leestekens is er natuurlijk niets aan de hand. Kijken wat er nu gebeurt.</p>

The rule is that the following elements should be included in the <p>-element:
<a>
<br />
<hr />
<span>
<em>
<strong>
<sub>
<sup>

Is this possible with xslt and how?
I think I should check whether the next-sibblings element-name is on the list and, if this is the case, include it. Problem is that I don't know how to do that.

Gert
 
What does your input look like?

Jon

"I don't regret this, but I both rue and lament it.
 
Input looks like this:
Code:
Hallo wereld ik ben <strong>vetgedrukt</strong>. En ik dan weer niet.
<p>Dit is een mooie tekst  gebruik van leestekens is er natuurlijk niets aan de hand. Kijken wat er nu gebeurt.</p>

Gert
 
This is actually quite complicated to do. I think recursion is probably the neatest way, and I may post that if I get bored, but first of all I came up with this (slighty messy) way:
Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
  <xsl:output method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>[/URL]
  <xsl:template match="/">
    <html>
      <head>
        <title>XHTML Page</title>
      </head>
      <body>
        <xsl:apply-templates select="content"/>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="content">
    <xsl:for-each select="*|text()">
      <xsl:choose>
        <xsl:when test="name(.) = 'p'">
          <xsl:copy-of select="."/>
        </xsl:when>
        <xsl:when test="name(.) = '' and (name((preceding-sibling::*|preceding-sibling::text())[count(current()/preceding-sibling::*|current()/preceding-sibling::text())]) = 'p' or not(preceding-sibling::*))">
         <xsl:variable name="firstp" select="following-sibling::p[1]"/>
          <xsl:variable name="ppos">
            <xsl:for-each select="following-sibling::*|following-sibling::text()">
              <xsl:if test="generate-id(.) = generate-id($firstp)">
                <xsl:value-of select="position()"/>
              </xsl:if>
            </xsl:for-each>
          </xsl:variable>
          <p>
            <xsl:copy-of select="."/>
            <xsl:copy-of select="(following-sibling::*|following-sibling::text())[position() &lt; $ppos]"/>
            <xsl:value-of select="$ppos"/>
          </p>
        </xsl:when>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

Jon

"I don't regret this, but I both rue and lament it.
 
Thank you Jon, it seems to work fine. But I have to test it some more and expand it a little bit, to make it work with other tags like <img> <ul> etcetera. So the <p> can be a <img> or a <ul> as well.

Gert
 
I pretty much feel like an idiot, but I'm still struggling with problem. I have the feeling I'm close to the solution, but I stil haven't got it working though. To give you a better idea of the XML I'm dealing with, I'll post the complete one instead of a fragment.

I made some modifications to the code of Jon to get rid of the xhtml-prefixes. Anyway, I hope someone (Jon for example ;-)) can have a look at it.
Code:
<cms:Component ID="cms:17-58781" IsEditable="false" xmlns:cms="[URL unfurl="true"]http://www.cms.com/ContentManager/5.0"[/URL] xmlns:xlink="[URL unfurl="true"]http://www.w3.org/1999/xlink">[/URL]
	<cms:Data>
		<cms:Title>De zomer komt met bakken uit de hemel</cms:Title>
		<cms:Type>Normal</cms:Type>
		<cms:Schema xlink:type="simple" xlink:title="Algemeen" xlink:href="cms17-58758-8"/>
		<cms:Content>
			<algemeen xmlns="[URL unfurl="true"]http://www.minvws.nl/intranet/schemas/algemeen">[/URL]
				<titel>De zomer komt met bakken uit de hemel</titel>
				<intro>Zoals gebruikelijk in Nederland kan je de zomer alleen herkennen aan de kalender. En aan de zomertijd natuurlijk, altijd lekker zo'n uurtje eerder licht, of langer licht. Wat was het nou??</intro>
				<anker>Ja</anker>
				<inhoud>
					<titel>Donder</titel>
					<tekst xmlns:xhtml="[URL unfurl="true"]http://www.w3.org/1999/xhtml">Lorum[/URL] ipsum, donder en bliksem, wat een herrie. Als dat zo doorgaat dan houdt het niet op. Maar na regen komt zonneschijn, da's een zekerheidje. 
<xhtml:p>En hier staat ook een p</xhtml:p>en hier weer niet. En hier <xhtml:strong>this word is strong</xhtml:strong>ook niet.</tekst>
				</inhoud>
				<inhoud>
					<titel>Bliksem</titel>
					<tekst xmlns:xhtml="[URL unfurl="true"]http://www.w3.org/1999/xhtml">Hete[/URL] bliksem, getverderrie, echt nie lekker. Altijd moeilijk testcontent tikken, maar het moet toch echt, anders hebben we niets te testen.</tekst>
				</inhoud>
				<datum>2005-07-08T13:33:45</datum>
				<breedtenavigatie>
					<titel>Van de redactie</titel>
					<tekst xmlns:xhtml="[URL unfurl="true"]http://www.w3.org/1999/xhtml">[/URL]
						<xhtml:p>Bla die bla die bla die bla.</xhtml:p>
					</tekst>
				</breedtenavigatie>
				<breedtenavigatie>
					<titel>Toelichting</titel>
					<tekst xmlns:xhtml="[URL unfurl="true"]http://www.w3.org/1999/xhtml">Toelichting?[/URL] Toelichting waarop dan?</tekst>
				</breedtenavigatie>
			</algemeen>
		</cms:Content>
	</cms:Data>
</cms:Component>

This is the XSL I'm using:
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] xmlns:algemeen="[URL unfurl="true"]http://www.minvws.nl/intranet/schemas/algemeen"[/URL] xmlns:extlink="[URL unfurl="true"]http://www.minvws.nl/intranet/schemas/externelink"[/URL] xmlns:cms="[URL unfurl="true"]http://www.tridion.com/ContentManager/5.0"[/URL] xmlns:cmsse="[URL unfurl="true"]http://www.tridion.com/ContentManager/5.1/cmsScriptAssistant"[/URL] xmlns:xlink="[URL unfurl="true"]http://www.w3.org/1999/xlink"[/URL] xmlns:x="[URL unfurl="true"]http://www.w3.org/1999/xhtml"[/URL] xmlns:ms="urn:schemas-microsoft-com:xslt" xmlns:dt="urn:schemas-microsoft-com:datatypes" xmlns:script="urn:script" exclude-result-prefixes="algemeen cmsse xlink xsl cms x ms dt extlink script ">
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
	<!-- Global Variables -->
	<xsl:variable name="CONTENTTYPE_NIEUWS">Nieuws</xsl:variable>
	<xsl:variable name="CONTENTTYPE_AGENDA">Agenda</xsl:variable>
	<xsl:variable name="SCHEMA_EXTERNELINK">Externe link</xsl:variable>
	<xsl:template match="/">
		<xsl:apply-templates select="//algemeen:tekst" />
	</xsl:template>
	<xsl:template match="*[local-name()='tekst']">   	
		<!-- <xsl:apply-templates select="node()|text()"/> -->
		<!-- Encapsulate all text-elements in paragraph tag -->
	    <xsl:for-each select="*|text()">
	      <xsl:choose>
	        <xsl:when test="local-name(.) = 'p'">
	        	<xsl:element name="{local-name()}">
	        		<xsl:value-of select="."/>
	        	</xsl:element>
	        </xsl:when>
	        <xsl:when test="local-name(.) = '' and (local-name((preceding-sibling::*|preceding-sibling::text())[count(current()/preceding-sibling::*|current()/preceding-sibling::text())]) = 'p' or not(preceding-sibling::*))">
	         <xsl:variable name="firstp" select="following-sibling::p[1]"/>
	          <xsl:variable name="ppos">
	            <xsl:for-each select="following-sibling::*|following-sibling::text()">
	              <xsl:if test="generate-id(.) = generate-id($firstp)">
	                <xsl:value-of select="position()"/>
	              </xsl:if>
	            </xsl:for-each>
	          </xsl:variable>
	          <p>
	            <xsl:copy-of select="."/>
	            <xsl:copy-of select="(following-sibling::*|following-sibling::text())[position() &lt; $ppos]"/>
	          </p>
	        </xsl:when>
	        <xsl:otherwise>
			<xsl:apply-templates select="." />
	        </xsl:otherwise>
	      </xsl:choose>
	    </xsl:for-each>
	    <!-- / Encapsulate all text-elements in paragraph tag -->		
	</xsl:template>
	<xsl:template match="x:font|x:u">
		<xsl:copy-of select="."/>
	</xsl:template>
	<xsl:template match="x:br">
		<xsl:element name="br"/>
	</xsl:template>
	<xsl:template match="x:*">
		<xsl:element name="{local-name()}">
			<xsl:for-each select="@*">
				<xsl:copy-of select="."/>
			</xsl:for-each>
			<xsl:apply-templates select="node()|text()"/>
		</xsl:element>
	</xsl:template>
	<xsl:template match="x:img">
		<div class="img">
			<img>
				<xsl:attribute name="src"><xsl:value-of select="cmsse:PublishBinary(string(@xlink:href))"/></xsl:attribute>
				<xsl:attribute name="alt"><xsl:value-of select="document(@xlink:href)//*[local-name()='alt']"/></xsl:attribute>
				<xsl:attribute name="width"><xsl:value-of select="@width"/></xsl:attribute>
				<xsl:attribute name="height"><xsl:value-of select="@height"/></xsl:attribute>
			</img>
		</div>
	</xsl:template>
	<xsl:template match="x:a">
		<xsl:variable name="linkedcomponentid" select="@xlink:href"/>
		<xsl:text disable-output-escaping="yes">&lt;% response.write _</xsl:text>
		<xsl:call-template name="getdynamiclink">
			<xsl:with-param name="linkedcomponentid" select="$linkedcomponentid"/>
			<xsl:with-param name="publicationid" select="/cms:Component/cms:Context/cms:Publication/@xlink:href"/>
			<xsl:with-param name="linktekst">
				<xsl:call-template name="escapeQuot">
					<xsl:with-param name="text" select="."/>
				</xsl:call-template>
			</xsl:with-param>
			<xsl:with-param name="showlinktekst">True</xsl:with-param>
			<xsl:with-param name="linktype" select="document($linkedcomponentid)/cms:Component/cms:Data/cms:Type"/>
		</xsl:call-template>
		<xsl:text disable-output-escaping="yes">%&gt;</xsl:text>
	</xsl:template>
	<xsl:template name="escapeQuot">
		<xsl:param name="text"/>
		<xsl:choose>
			<xsl:when test="contains($text, '&quot;')">
				<xsl:variable name="bufferBefore" select="substring-before($text, '&quot;')"/>
				<xsl:variable name="newBuffer" select="substring-after($text, '&quot;')"/>
				<xsl:value-of select="$bufferBefore"/>
				<xsl:text disable-output-escaping="no">""</xsl:text>
				<xsl:call-template name="escapeQuot">
					<xsl:with-param name="text" select="$newBuffer"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$text"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<ms:script language="VBScript" implements-prefix="script">
            Set objTDSE = CreateObject("TDS.TDSE")
            objTDSE.Initialize
            Function renderBinary(uriBinary)
                        uriBinaryRenderCT = "cms:17-58890-32"
                        Set objBinary = objTDSE.GetObject(uriBinary, 1)
                        objBinary.Render(uriBinaryRenderCT)
                        renderBinary= uriBinary
            End Function
</ms:script>
</xsl:stylesheet>

and this is the current output
Code:
<p>Lorum ipsum, donder en bliksem, wat een herrie. Als dat zo doorgaat dan houdt het niet op. Maar na regen komt zonneschijn, da's een zekerheidje. 
</p>
<p>En hier staat ook een p</p>
<p>en hier weer niet. En hier </p>
<strong>this word is strong</strong>ook niet.
<p>Hete bliksem, getverderrie, echt nie lekker. Altijd moeilijk testcontent tikken, maar het moet toch echt, anders hebben we niets te testen.</p>
<p>Bla die bla die bla die bla.</p>
<p>Toelichting? Toelichting waarop dan?</p>

And this is what I want:
Code:
<p>Lorum ipsum, donder en bliksem, wat een herrie. Als dat zo doorgaat dan houdt het niet op. Maar na regen komt zonneschijn, da's een zekerheidje. 
</p>
<p>En hier staat ook een p</p>
<p>en hier weer niet. En hier <strong>this word is strong</strong>ook niet.</p>
<p>Hete bliksem, getverderrie, echt nie lekker. Altijd moeilijk testcontent tikken, maar het moet toch echt, anders hebben we niets te testen.</p>
<p>Bla die bla die bla die bla.</p>
<p>Toelichting? Toelichting waarop dan?</p>

Gert
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top