[XML/XSLT] Linebreakes in HTML binnen XML code replacen

Pagina: 1
Acties:

  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Topicstarter
Ik probeer om een find en replace uit te voeren in HTML code binnen XML. Ik heb namelijk een JavaScript functie die geen enters in zijn argumenten mag hebben; dus wil ik hier een \n of <br /> van maken. Het probleem is dat ik het niet voor elkaar krijg. Momenteel gebeuren er in mijn XSL twee zaken

• de XML code wordt doorlopen en met een substring-before en substring-after worden enters vervangen
• [url]a[/], b en i elementen worden door <a>, <b> en <i> html code vervangen

Het lukt echter niet om beide zaken tegelijk uit te voeren :(

Code om Enters in HTML code te vervangen door <br />
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[...]
    <xsl:template name="linebreaks">
         <xsl:param name="string"/>
         <xsl:choose>
              <xsl:when test="contains($string, '
')">
                    <xsl:value-of select="substring-before($string, '
')"/>
                    <br />
                    <xsl:call-template name="linebreaks">
                         <xsl:with-param name="string" select="substring-after($string, '
')"/>
                    </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                    <xsl:apply-templates />
                    <xsl:value-of select="$string"/>
              </xsl:otherwise>
         </xsl:choose>
    </xsl:template>
[...]

code om html code te converteren
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[...]
    <!--xsl:template match="a|A">
        <xsl:text disable-output-escaping="yes">&lt;a href='</xsl:text>
        <xsl:value-of select="@href" />
        <xsl:text disable-output-escaping="yes">'&gt;</xsl:text>
        <xsl:apply-templates />
        <xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text>
    </xsl:template>

    <xsl:template match="b|B">
        <xsl:text disable-output-escaping="yes">&lt;b&gt;</xsl:text>
        <xsl:apply-templates />
        <xsl:text disable-output-escaping="yes">&lt;/b&gt;</xsl:text>
    </xsl:template-->

    <!--xsl:template match="b|B|i|I|LI|li|UL|ul|OL|ol|P|p">
        <xsl:copy>
            <xsl:apply-templates select="b|B|i|I|LI|li|UL|ul|OL|ol|P|p"/>
        </xsl:copy>
    </xsl:template-->
</xsl:stylesheet>
[...]
De input XML is
XML:
1
2
3
4
5
6
7
8
9
10
[...]
<?xml version="1.0"?>
<site>
    <paragraph>
        A new paragraph
        <B>Sitemap</B> intro. And a <a href='http://www.tweakers.net'>link test</a> to <I>tweakers.net
        </I>A line break
    </paragraph>
</site>
[...]
Gewenste HTML code:
HTML:
1
2
3
4
5
[...]
    <body>
        <p>A new paragraph<br /><B>Sitemap</B> intro. And a <a href='http://www.tweakers.net'>link test</a> to <I>tweakers.net<BR /></I>A line break</p>
    </body>
[...]

Heeft iemand enig idee hoe we een resultaat krijgen waarbij:
• de HTML markup behouden blijft;
• de enters worden vervangen door <br />'s

[ Voor 40% gewijzigd door Spider.007 op 08-01-2004 15:47 ]

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Volgens mij moet je je hele benadering van xslt eens anders gaan doen. Die output-escaping toestanden en het gebruik van entities voor het genereren van html is echt verschrikkelijk lelijk en onnodig.

Voor bijvoorbeeld je 'a' template:
code:
1
2
3
4
5
<xsl:template match="a">
   <a>
      <xsl:attribute name="href"><xsl:value-of select="@href" /></xsl:attribute>
   </a>
</xsl:template>

zeg nou zelf, wat is mooier? ;) Of gebruik desnoods gewoon een xsl:copy

Maar goed, om even op je vraag terug te komen: waarom gebruik je niet een translate () om een om te zetten in een '\n' ?

[ Voor 5% gewijzigd door drm op 08-01-2004 15:51 ]

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Topicstarter
Deze benadering is noodzakelijk omdat er wijzigingen moeten worden doorgevoerd in de href die wordt ge-output.

Je tweede idee hebben we reeds geprobeerd; het probleem is dat translate slechts 1 character voor 1 ander character kunnen vervangen. (translate('abc', 'abc', 'AB') heeft als output 'AB'. Ook zullen de HTML tags niet meer worden meegenomen in de output.

De kunst is dus om de enters goed te vervangen en tegelijkertijd de HTML markup te behouden (a, b, p en i tags ed).

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Spider.007:
Deze benadering is noodzakelijk omdat er wijzigingen moeten worden doorgevoerd in de href die wordt ge-output.
Dat lijkt mij een beetje onzin. waarom zou dat met een xsl:attribute niet (goed) gaan :?
Je tweede idee hebben we reeds geprobeerd; het probleem is dat translate slechts 1 character voor 1 ander character kunnen vervangen. (translate('abc', 'abc', 'AB') heeft als output 'AB'.
Daar heb je gelijk in, ja, mijn fout. Vreemd genoeg heeft XPath ook geen normale replace functie.
Ook zullen de HTML tags niet meer worden meegenomen in de output.
Nou, dat ligt er maar aan hoe je het aanpakt natuurlijk ;)

code:
1
2
3
4
5
6
7
8
9
10
11
<xsl:template match="text()">
   <xsl:call-template name="linebreaks">
      <xsl:with-param name="string" select="." />
   </xsl:call-template>
</xsl:template>

<xsl:template match="a|b|i">
   <xsl:copy>
      <xsl:apply-templates select="*|text()" />
   </xsl:copy>
</xsl:template>
Werkt prima. Dat bedoel je toch?

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Topicstarter
<xsl:template name="linebreaks">
<xsl:param name="string"/>
<xsl:choose>
<xsl:when test="contains($string, ' ')">
<xsl:value-of select="substring-before($string, ' ')"/>
<br/>
<xsl:call-template name="linebreaks">
<xsl:with-param name="string" select="substring-after($string, ' ')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="text()">
<xsl:call-template name="linebreaks">
<xsl:with-param name="string" select="current()" />
</xsl:call-template>
</xsl:template>

<xsl:template match="a|A">
<xsl:param name="href" select="@href" />

<xsl:text disable-output-escaping="yes"><a href='</xsl:text>
<xsl:value-of select="$href" />
<xsl:text disable-output-escaping="yes">'></xsl:text>
<xsl:apply-templates />
<xsl:text disable-output-escaping="yes"></a></xsl:text>
</xsl:template>

<xsl:template match="b|B">
<xsl:text disable-output-escaping="yes"><b></xsl:text>
<xsl:apply-templates />
<xsl:text disable-output-escaping="yes"></b></xsl:text>
</xsl:template>

<xsl:template match="p|P">
<xsl:text disable-output-escaping="yes"><p></xsl:text>
<xsl:apply-templates />
<xsl:text disable-output-escaping="yes"></p></xsl:text>
</xsl:template>

<xsl:template match="i|I">
<xsl:text disable-output-escaping="yes"><i></xsl:text>
<xsl:apply-templates />
<xsl:text disable-output-escaping="yes"></i></xsl:text>
</xsl:template>

<xsl:template match="br|BR">
<xsl:text disable-output-escaping="yes"><br /></xsl:text>
</xsl:template>

---

Enig commentaar op deze code:
- Om de één of andere vage reden krijg ik het href attribuut van de a tag alleen weergegeven als ik dit attribuut eerst opsla in een variable, waarom ik het attribuut niet direct (d.m.v. xsl:value-of select="@href") kan benaderen is mij een raadsel.
- Voor zover ik weet moeten alle tags wel ge-escaped worden, omdat anders alsnog enters worden weergegeven in het resultaatbestand als deze enters binnen de elementen bestaan. We gebruiken Xalan (versie 2.x), misschien dat een andere parser hier anders mee omgaat. Om deze reden maak ik in dit geval geen gebruik van xsl:attibute.

Mijn dank voor je hulp, ik was er niet op gekomen om alle text() elementen te matchen, dat was de voornaamste reden waarom ik niet dit probleem kon oplossen.

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

We gebruiken Xalan (versie 2.x), misschien dat een andere parser hier anders mee omgaat. Om deze reden maak ik in dit geval geen gebruik van xsl:attibute.
Aha. Waarschijnlijk moet je dan gewoon even in je xsl:output element een indent="no" attribuut zetten.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Topicstarter
drm schreef op 09 januari 2004 @ 13:08:
[...]
Aha. Waarschijnlijk moet je dan gewoon even in je xsl:output element een indent="no" attribuut zetten.
Helaas had het uitzetten slechts tot gevolg dat de HTML code achter elkaar werd geplakt. Wat ons betreft is het probleem in ieder geval opgelost; wij waren er van overtuigd dat het onmogelijk was; zelfs guru's op XSLT mailinglist kregen dit niet voor elkaar :D

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate

Pagina: 1