Avatar billede bned1232 Nybegynder
27. august 2008 - 10:37 Der er 13 kommentarer

transformer xml/html til plain text

Hej

Jeg har en xml fil, hvori der er en node, der indeholder data i form af tekst og html-tags. Jeg skal have dette transformeret over til plain text, så det kan sendes ud på mail(det skal kunne forståes af alle uanset opsætning af mailklient - derfor plain text).

XML ser således ud

<Content>
- <span class="norm">
  gh gfh gfh gfh gfh gfh gfh gfh gh grwefds gf f g
  <br />
<strong>
    <br />
  bgfhghgh
  </strong>
  <br />
  <br />
<ul>
  <li>Hospitaler</li>
  <li>trytrytyty</li>
  <li>f fg f g dfsdfdfli>
  <li> f gf gf gd</li>
  <li>fg dfg f gf fd f </li>
  <li> gfgf f fdg li>
  <li>dvfd  ffg </li>
  </ul>
  </span>
<ul>
  <li />
  </ul>
  </Content>

der skal ske en transformation, således at nogle af formatteringerne bevares i plain text, f.eks mellemrum. Resten fjernes, dvs man skal ind og replace visse html tags og så fjerne resten. XML-dokumentet har altid en rodnode, der hedder Content, men al teksten og html'en inde i den er vilkårlig fra gang til gang, man sender ud(det sker via CMS).

Det skal gøres ved hjælp af xslt. Jeg har kopieret al indholdet fra noden ind i en xslt:variable er derefter forsøgt at replace ved hjælp af substring-before og substring-after. Den ser blot bort fra alle html-tags, som den vel opfatter som xml.

Men hvordan griber jeg det så an?
Avatar billede jokkejensen Novice
27. august 2008 - 11:08 #1
Personligt havde jeg valgt at lave en xslt extension, der med regex filtererede det uønskede fra.

Men...

Først skal du kunne søge og erstatte i en streng:

    <xsl:template name="replace">
        <xsl:param name="string" />
        <xsl:param name="from" />
        <xsl:param name="to" />

        <xsl:choose>
            <xsl:when test="contains($string, $from)">
                <xsl:value-of select="substring-before($string, $from)" />
                <xsl:copy-of select="$to" />
                <xsl:call-template name="replace">
                    <xsl:with-param name="string" select="substring-after($string, $from)" />
                    <xsl:with-param name="from" select="$from" />
                    <xsl:with-param name="to" select="$to" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$string" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>


Du kalder bare templaten med :

<xsl:call-template name="replace">
    <xsl:with-param name="string" select="$Variable" />
    <xsl:with-param name="from" select="''" />
    <xsl:with-param name="to" select="''"></xsl:with-param>
</xsl:call-template>

Da xslt ikke er specielt egnet til at manipulere strenge på den måde, vil det kræve en lang række søg/erstat. Jeg har før set mig nødsaget til lignende:

<!-- første -->
<xsl:variable name="Variable2">
<xsl:call-template name="replace">
    <xsl:with-param name="string" select="$Variable" />
    <xsl:with-param name="from" select="''" />
    <xsl:with-param name="to" select="''"></xsl:with-param>
</xsl:call-template>
</xsl:varialbe>

<!-- Anden -->
<xsl:variable name="Variable3">
<xsl:call-template name="replace">
    <xsl:with-param name="string" select="$Variable2" />
    <xsl:with-param name="from" select="''" />
    <xsl:with-param name="to" select="''"></xsl:with-param>
</xsl:call-template>
</xsl:varialbe>

<!-- and so on -->

Det kan godt være der findes en lettere måde.

Bemærk at <li> nok skal findes med &lt;li&gt; altså xml entities for speciel karakter.

/JJ
Avatar billede jokkejensen Novice
27. august 2008 - 11:11 #2
Alternativt kunne du med msxsl:node-set() danne variablen om til et nodeset, og iterere gennem templates der rammer de forskellige tags og erstatte dem på den måde.

/JJ
Avatar billede bned1232 Nybegynder
27. august 2008 - 11:58 #3
Dit første forslag er det jeg selv har prøvet, men som blot resulterede i, at der blev set fra html. Jeg har sågar prøvet at lave en variable, hvor jeg blot skrev noget tekst og html kode inde i og der bliver stadigvæk set bort fra html, f.eks

<xsl:variable name="udsend">gf gff  <br /> fdsdsf <strong>oppoj</strong>  gfg fg g g </xsl:variable>

Der ses blot bort fra html, når man vælger  <xsl:with-param name="string" select="$udsend" />

Det eneste tidspunkt, hvor jeg rent faktisk fik noget html ud var da jeg brugte <xsl:copy-of select="$udsend" />.

Det betyder på at html bliver opfattet som xml nodes og derfor ses der bort fra dem og derfor virker den løsning du forslog ikke. Eller er jeg helt på vildspor?
Avatar billede jokkejensen Novice
27. august 2008 - 13:17 #4
Øhmm åben lige xml arket i IE7, og fortæl mig om markuppen er sort, eller om du kan folde den ud og ind som resten af xml arket. Upload evt et dump et eller andet sted.

Er den sort, er det en streng, hvis du kan folde den ud og ind er det xml.. Så er det nok lettere at ramme den med nogle templates.
Avatar billede jokkejensen Novice
27. august 2008 - 13:18 #5
vis kilde afslører det også.. så vil der stå &lt;strong&gt; og ikke <strong>
Avatar billede bned1232 Nybegynder
01. september 2008 - 11:31 #6
Det er et node-set, så jeg har bestemt mig for at iterere igennem det, som du foreslog som løsning nummer 2
Avatar billede bned1232 Nybegynder
01. september 2008 - 11:36 #7
ghjhjghjghjhgjhj
Avatar billede bned1232 Nybegynder
01. september 2008 - 11:38 #8
Hvordan fanden accepterer jeg dit svar, jeg klikker og klikker og klikker på accepter og det bliver ikke accepteret. der står at jeg skal markere indlægget, men der er ingen steder at markere.
Avatar billede jokkejensen Novice
01. september 2008 - 15:31 #9
jeg skal lige ligge et svar :)..

Men sig til hvis det driller på den måde, så vil jeg gerne hjælpe, ellers beholder du bare points :)
Avatar billede bned1232 Nybegynder
04. september 2008 - 11:19 #10
Hov et spørgsmål til. Jeg er nu ved at iterere igennem nodesettet, så kommer jeg f.eks til følgende i node-settet:

<p> d fdf dfdf df df <br/>  fg fgdf g <br/><br/> cvxcvcxv</p>

Altså tags inde i tags.

Det skal så konverteres om til noget text, hvilket jeg gør på følgende måde:

<xsl:apply-templates select="RichTextEdition/Content" />

<xsl:template match="Content">

<xsl:for-each select="//*">

<xsl:if test="name()='li'">
    * <xsl:value-of select="."/>
</xsl:if>

<xsl:if test="name()='br'">
<xsl:text>
</xsl:text>
</xsl:if>

<xsl:if test="name()='p'">
        <xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>

Når jeg så hiver værdien ud af p-taget, så ser den jo bort fra alle br-tags, så får jeg det jo ikke i den rigtige rækkefølge

Hvordan håndterer jeg den situation?

mvh

Bo
Avatar billede jokkejensen Novice
04. september 2008 - 16:26 #11
Er det kun breaks der driller ? - og bliver de opfattet som tomme noder ?

Hvis problemet er at <br /> skal væk men der stadig skal beholdes en form for linie skift, vil jeg nok bare gemme det hele i en variable, og søge og erstatte i den til sidst efter <br />..

altså brug:
http://www.topxml.com/code/cod-422_10073_how-to-do-a-search-and-replace-in-xslt.aspx

Til at erstatte i variablen efter ønske til sidst, sig til hvis jeg har misforstået noget.

noget ala:

    <xsl:template match="Content">
        <xsl:variable name="TempContent">
            <xsl:for-each select="//*">

                <xsl:if test="name()='li'">
                    * <xsl:value-of select="."/>
                </xsl:if>

                <xsl:if test="name()='br'">
                    <xsl:text>
                </xsl:text>
                </xsl:if>

                <xsl:if test="name()='p'">
                    <xsl:value-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>

                <!-- //// replace !!! -->
    </xsl:template>
Avatar billede bned1232 Nybegynder
04. september 2008 - 17:03 #12
Problemet et netop, at jeg ikke kan lave en search og replace, da det bliver opfattet som et node-set. Alle html tags bliver altså opfattet som xml. Når jeg laver en search og replace ses der derfor bort fra alle html-tags inklusive <br/>. Derfor er jeg nødt til at iterere.
Avatar billede jokkejensen Novice
11. september 2008 - 14:11 #13
narj, for ovenstående replace.

Noget ala:

<xsl:with-param name="text">
    <xsl:value-of select="$din variable" disable-output-escaping="yes" />       
</xsl:with-param>
<xsl:with-param name="replace" select="'&gt;br /&lt;'"
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester