Question

Imaginez que j'ai le fichier XML suivant:

< a > avant < b > moyen < / b > après < / a >

Je veux le convertir en quelque chose comme ceci:

< a > beforemiddi après < / a >

En d'autres termes, je souhaite obtenir tous les nœuds enfants d'un certain nœud et les déplacer dans le nœud parent dans l'ordre. Cela revient à faire cette commande: & "; Mv ./directory/*. &" ;, mais pour les noeuds xml.

J'aimerais faire cela en utilisant des outils de ligne de commande Unix. J'ai essayé avec xmlstarlet, un puissant manipulateur XML en ligne de commande. J'ai essayé de faire quelque chose comme ça, mais ça ne marche pas

echo & "; < a > avant < b > moyen < / b > après < ; / a > " | xmlstarlet ed -m " // b / * " " .. "

Mise à jour: les modèles XSLT conviennent, car ils peuvent être appelés à partir de la ligne de commande.

Mon objectif ici est de "supprimer les liens d'une page XHTML", c'est-à-dire remplacer l'emplacement du lien par le contenu de la balise link.

Était-ce utile?

La solution

Si votre objectif actuel est de supprimer les liens d'une page Web, vous devez utiliser une feuille de style comme celle-ci, qui correspond à tous les éléments XHTML <a> (je suppose que vous utilisez XHTML?) et applique simplement des modèles à leur contenu:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:h="http://www.w3.org/1999/xhtml"
  exclude-result-prefixes="h">

<!-- Don't copy the <a> elements, just process their content -->
<xsl:template match="h:a">
  <xsl:apply-templates />
</xsl:template>

<!-- identity template; copies everything by default -->
<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Cette feuille de style traitera une situation dans laquelle quelque chose est imbriqué dans l'élément <p> que vous souhaitez conserver, tel que:

<p>Here is <a href="....">some <em>linked</em> text</a>.</p>

que vous voulez sortir comme:

<p>Here is some <em>linked</em> text.</p>

Et cela traitera de la situation où le lien est imbriqué dans un élément inattendu entre le parent habituel (l'élément <=>) et l'élément <=>, tel que:

<p>Here is <em>some <a href="...">linked</a> text</em>.</p>

Autres conseils

Exemple de fichier d'entrée (test.xml):

<?xml version="1.0" encoding="UTF-8"?>
<test>
<x>before<y>middle</y>after</x>
<a>before<b>middle</b>after</a>
<a>before<b>middle</b>after</a>
<x>before<y>middle</y>after</x>
<a>before<b>middle</b>after</a>
<embedded>foo<a>before<b>middle</b>after</a>bar</embedded>
</test>

Feuille de style XSLT (collapse.xsl:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

      <xsl:template match="a">
        <xsl:copy>
          <xsl:value-of select="."/>
        </xsl:copy>
      </xsl:template>

    </xsl:stylesheet>

Exécuter avec XmlStarlet avec

xml tr collapse.xsl test.xml

Produit:

<?xml version="1.0"?>
<test>
<x>before<y>middle</y>after</x>
<a>beforemiddleafter</a>
<a>beforemiddleafter</a>
<x>before<y>middle</y>after</x>
<a>beforemiddleafter</a>
<embedded>foo<a>beforemiddleafter</a>bar</embedded>
</test>

Le premier modèle de la feuille de style est la transformation d'identité de base (il suffit de copier l'intégralité de votre document XML d'entrée). Le deuxième modèle correspond spécifiquement aux éléments que vous voulez "réduire" et ne fait que copier les balises et insérer la valeur de chaîne de l'élément (= concaténation de la valeur de chaîne des nœuds descendants).

Dans XSLT, vous pouvez simplement écrire:

<xsl:template match="a"><a><xsl:apply-templates /></a></xsl:template>

<xsl:template match="a/b"><xsl:value-of select="."/></xsl:template>

Et vous obtiendrez:

<a>beforemiddleafter</a>

Donc, si vous voulez le faire facilement, vous pouvez simplement créer une feuille de style XSL et exécuter votre fichier XML par ce biais.

Je réalise que ce n'est pas ce que vous avez dit que vous aimeriez faire (en utilisant la ligne de commande Unix), cependant. Je ne connais rien à Unix, alors peut-être que quelqu'un d'autre pourra compléter, par exemple. une sorte d'appels en ligne de commande pouvant exécuter ce qui précède.

Utilisation de xmlstarlet:

xmlstr='<a>before<b>middle</b>after</a>'
updatestr="$(echo "$xmlstr" | xmlstarlet sel -T -t -m "/a/b" -v '../.' -n | sed -n '1{p;q;}')"
echo "$xmlstr" | xmlstarlet ed -u "/a" -v "$updatestr"

Avez-vous essayé cela?

file.xml

<r>
    <a>start<b>middle</b>end</a>
</r>

template.xsl

<xsl:template match="/">
    <a><xsl:value-of select="r/a" /></a>
</xsl:template>

output

<a>startmiddleend</a>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top