Avatar billede davidfossil Nybegynder
21. november 2006 - 11:05 Der er 5 kommentarer og
2 løsninger

Namespaces ved copy-of

I mit XML input dokument har jeg noget lign. følgende:

<foo xmlns="http://foobar.org/" xmlns:html="http://www.w3.org/1999/xhtml">
  <bar>
    <html:p>
      Her er noget tekst i en paragraf - noget er med <html:strong>fed skrift</html:strong>.
    </html:p>
  </bar>
</foo>

I min XSLT ønsker jeg at selecte alle elementer af typen <bar> og udskrive deres indhold incl. underliggende elementer i resultatet. Da resultatet er en XHTML-side vil jeg gerne have alle html-prefixes fjernet.

Jeg har rodet lidt med <xsl:copy-of> uden held. Jeg forestiller mig min XSLT hvilket namespace der er default i mit result, og således få copy-of til at fjerne de upassende prefix. Er det helt galt? Hvordan gør man ellers? Det må være en temmelig triviel opgave, men jeg er virkelig gået kold i namespaces =\
Avatar billede davidfossil Nybegynder
21. november 2006 - 17:21 #1
Er stadig helt på bar bund her. Har forsøgt at indsætte følgende i min XSLT:
<xsl:namespace-alias stylesheet-prefix="html" result-prefix="#default"/>

Med dette element i starten af mit <xsl:stylesheet>, kan jeg skrive <html:hr /> i min XSLT og få det spyttet ud som <hr /> i resultatet. Desværre har det ingen indvirkning på elementer som kopieres fra mit XML-input vha. <xsl:copy-of> og disse beholder således deres prefix og får tilføjet en namespace attribut i resultatet.

Hvad er det jeg gør galt?
Avatar billede Slettet bruger
21. november 2006 - 20:39 #2
Du er på rette spor mht. at bruge <xsl:namespace-alias> - men du kan ikke komme uden om <xsl:copy-of /> problemet uden at droppe den, og bruge en rekursiv template i stedet for, fordi <xsl:copy-of /> laver det der hedder en "deep copy" som inkluderer alle namespaces der er i "scope" for det element der laves en kopi af. Den er derfor tvunget til at kopiere samtlige namespaces der gælder, dvs. er blevet erklæret længere oppe i dokumentet.

Du kan dog udskyde nogle af dem vha. attributten "exclude-result-prefixes" på <xsl:output /> - herved genereres en namespace node først når et element bruger det.

/CS
Avatar billede davidfossil Nybegynder
21. november 2006 - 22:37 #3
Kan du give et eksempel på hvordan jeg implementerer en sådan rekursiv template? Nedenstående er en meget simplificeret af min XSLT-fil som du evt. kan tilføje det nødvendige til:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:html="http://www.w3.org/1999/xhtml">
  <xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="yes"/>
  <xsl:namespace-alias stylesheet-prefix="html" result-prefix="#default"/>
 
  <xsl:template match="/xhtml">
    <xsl:copy-of select="*" />
  </xsl:template>
</xsl:stylesheet>

Jeg gætter på at der skal tilføjes en ny <xsl:template> som matcher alt fra det namespace som er knyttet til prefix html og spytter det ud uden prefix, men jeg kan ikke rigtig lure hvordan det er meningen at jeg skal gøre dette?

På forhånd tak :)
Avatar billede Slettet bruger
21. november 2006 - 23:01 #4
Det kan jeg da :-)

Flg. template kopierer rekursivt vha. <xsl:copy> (en såkaldt "shallow copy"):

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

Du kopierer så elementer fra xhtml-namespace'et sådan (ex. <html:body>):

  <xsl:apply-templates select="html:body" mode="copy" />

Håber det hjalp.

/CS
Avatar billede davidfossil Nybegynder
22. november 2006 - 08:41 #5
Følgende er hvad jeg nu har indsat i min XSLT:
<xsl:template match="/foo/bar">
    <xsl:apply-templates select="html:*" mode="copy" />
</xsl:template>

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


Effekten er desværre den samme som med <copy-of>. Jeg får stadig html-prefixes og namespacedeklerationer på alt hvad der kopieres. Er der noget jeg har gjort forkert?
Avatar billede janegil Nybegynder
22. november 2006 - 19:03 #6
Er det ikke noe med at XSLT har problemer med implisitt namespace? At du enten må bruke prefix for foobar-namespace i kildedokumentet, eller bruke match=foo:bar i XSLT for å matche en bar i kilden.

Ikke at jeg hvordan dette kan hjelpe deg - det er bare et gammelt minne om et problem i samme gate.
Avatar billede davidfossil Nybegynder
23. november 2006 - 11:19 #7
Jeg er ikke helt sikkert på om jeg forstod janegil's indlæg, men jeg er i hvert fald nået et stykke videre nu. Faktisk virker mit XSLT nu som den skal, pånær en lille detalje som jeg flytter til et nyt spg: http://www.eksperten.dk/spm/746592

Her er hvad jeg gjorde:

<xsl:template match="/foo/bar">
    <xsl:apply-templates mode="rename" />
</xsl:template>

<xsl:template match="*" mode="rename">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates mode="rename"/>
    </xsl:element>
</xsl:template>

Mange tak for hjælpen :)
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



Seneste spørgsmål Seneste aktivitet
I går 23:37 Poe strøm Af lurup i LAN/WAN
I går 14:46 GIF-EDITOR Af snestrup2000 i Billedbehandling
I går 14:03 Logge ind Af Bob i PC
I går 12:12 2 skærme - 1 virker - den anden siger No signal Af eksmojo i Skærme
I går 10:33 openvpn projekt Af dcedata1977 i Windows