Problème de balises à fermeture automatique XSLT

J'utilise xslt pour transformer un fichier xml en html. Le moteur. net xslt continue de me servir des balises à fermeture automatique pour les balises vides.

Exemple:

<div class="test"></div> 

Devient

<div class="test" />

Le premier est html valide, tandis que le second est HTML illégal et rend mal. Ma question Est : Comment puis-je dire au moteur xslt (XslCompiledTransform) de ne pas utiliser de balises à fermeture automatique.

Si ce n'est pas possible, Comment puis-je dire à mon navigateur (IE6+ dans ce cas) d'interpréter les balises à fermeture automatique correctement.

23
demandé sur VH-NZZ 2009-05-20 16:55:44

11 réponses

Si vous utilisez XmlWriter comme flux de sortie, utilisez plutôt HTMLTextWriter. XMLWriter reformatera votre sortie HTML en XML.

11
répondu catalpa 2009-05-20 15:29:23

Changez votre méthode xsl:output pour qu'elle soit html (au lieu de xml).

, Ou l'ajouter si vous n'avez pas déjà l'élément

<xsl:output method="html"/>
22
répondu Harry Lime 2009-05-20 12:59:29

Une solution de contournement peut être d'insérer un élément de commentaire pour forcer la génération de fermeture non automatique:

<script type="text/javascript" src="nowhere.js">
<xsl:comment></xsl:comment>
</script>

Ce n'est pas une jolie soloution, mais ça marche: -)

/ Sten

14
répondu Netsi1964 2012-01-23 12:17:45
4
répondu Thorgeir 2010-09-15 15:53:21

Vous ne pouvez pas dire à votre navigateur de gérer le HTML invalide en tant que HTML - vous avez de la chance qu'il comprenne du HTML malformé. :)

Certainement le faire dans votre feuille de style:

<xsl:output method="html"/>

Mais, si votre document source a des espaces de noms, cela ne fera pas l'affaire. Les processeurs XSLT semblent changer silencieusement la méthode de sortie en XML si des nœuds d'espace de noms sont présents dans la sortie.

Vous devez remplacer toutes les instances de <xsl:copy-of> et <xsl:copy> par des créations d'éléments avec juste le nom local, par exemple

<xsl:template match="*">
   <xsl:element name="{local-name()}">
     <xsl:apply-templates/>
   </xsl:element>
</xsl:template>

Voir

Etc.

2
répondu Steven Huwig 2009-05-20 13:08:45

Pour moi, c'était un problème dans le script balise. Je l'ai résolu en le remplissant avec un point-virgule (;)

<script type="text/javascript" src="somewhere.js">;</script>
2
répondu Yajo 2010-11-24 15:22:53

J'avais l'habitude de mettre un élément <xsl:text> à l'intérieur, comme:

<script type="text/javascript" src="/scripts/jquery.js"><xsl:text> </xsl:text></script>
2
répondu kernel 2011-07-18 22:05:57

Il y a quelques choses que vous devez faire attention:

  1. dans votre utilisation xsl
  2. Définissez OutputSettings dans votre sortie XmlWriter
  3. dans le code Html de votre xsl, Ne définissez pas d'attributs dans la balise html comme ceci mais utilisez à la place.

Ceci est un morceau de code de travail:

string xmlStr = "<?xml version='1.0' encoding='UTF-8'?><Data></Data>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlStr);
string xslContents = @"
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'  
xmlns:msxsl='urn:schemas-microsoft-com:xslt' exclude-result-prefixes='msxsl'>
<xsl:output method='html' version='4.0' omit-xml-declaration='yes' indent='yes'/>
<xsl:template match='Data'>
<html>
<body>
    <div></div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>";
XslCompiledTransform xsl = new XslCompiledTransform();
xsl.Load(XmlReader.Create(new StringReader(xslContents)));
StringWriter result = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(result, xsl.OutputSettings))
{
    xsl.Transform(doc, null, writer);
}
System.Diagnostics.Debug.Write( result.ToString());
1
répondu Renzo Ciot 2014-04-06 07:10:47

Vient de rencontrer le même problème avec le XSL de PHP 5, avec output / @ method = html. Il semble que l'attribution d'un attribut de valeur vide entraînera la sortie d'éléments en tant que balises non-fermées non-fermées et non-fermées:

<input type="text" name="foo" value="{my-empty-value}" />

Résultats dans:

<input type="text" name="foo" value="">

Une solution possible consiste à ajouter conditionnellement l'attribut:

<xsl:if test="string-length(my-empty-value) > 0">
    <xsl:attribute name="value">
        <xsl:value-of select="my-empty-value" />
    </xsl:attribute>
</xsl:if>

Résultant en:

<input type="text" name="foo" />
0
répondu Brandon Hill 2012-09-24 14:57:36

J'utilise ce qui suit chaque fois que je souhaite empêcher un élément de fermeture automatique:

<xsl:value-of select="''" />

Cela trompe le moteur de rendu en croyant qu'il y a du contenu à l'intérieur de l'élément, et empêche donc l'auto-fermeture.

C'est un peu une solution laide donc je recommande de le contenir dans un modèle descriptif et de l'appeler à chaque fois:

<xsl:template name="PreventSelfClosure">
   <xsl:value-of select="''" />
</xsl:template>


<div class="test">
   <xsl:call-template name="PreventSelfClosure"/>
</div>

Cela rendra alors le suivant:

<div class="test"></div>

Http://curtistimson.co.uk/post/xslt/how-to-prevent-self-closing-elements-in-xslt/

0
répondu Curt 2017-08-21 10:58:58

Le moyen simple que j'ai trouvé était de créer une nouvelle classe XmlTextWriter pour remplacer la méthode WriteEndElement, forçant la balise non fermante et transmettre le processus de sérialisation en tant que paramètre.

public class MyXmlTextWriter : XmlTextWriter
{
    public MyXmlTextWriter(Stream stream) : base(stream, Encoding.UTF8)
    { }
    public MyXmlTextWriter(TextWriter stream) : base(stream)
    { }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}
0
répondu gblmarquez 2018-02-20 23:43:16