Das Verschieben des untergeordneten Knoten eines XML-Knotens nach oben
-
02-07-2019 - |
Frage
Stellen Sie sich vor ich habe die Folling XML-Datei:
Ich mag es konvertieren in etwa so aus:
Mit anderen Worten möchte ich alle untergeordneten Knoten eines bestimmten Knoten zu bekommen, und sie an den übergeordneten Knoten, um zu bewegen. Das ist wie Sie diesen Befehl ausführen: "mv ./directory/*"., Aber für XML-Knoten
Ich mag die Unix-in mit Kommandozeilen-Tool tun. Ich habe mit xmlstarlet versucht, die eine leistungsfähige XML-Manipulator-Befehlszeile ist. Ich habe versucht, so etwas wie dies zu tun, aber es funktioniert nicht
echo " vor Mitte nach " | xmlstarlet ed -m "// b / *" ".."
Update: XSLT-Templates sind in Ordnung, können, da sie von der Kommandozeile aufgerufen werden
.Mein Ziel hier ist ‚die Links von einer XHTML-Seite entfernen‘, mit anderen Worten ersetzen, wo der Link war, mit dem Inhalt der Link-Tags.
Lösung
Wenn Ihr eigentliches Ziel ist es, die Links von einer Webseite zu entfernen, dann sollten Sie ein Stylesheet wie folgt verwenden, die alle Elemente <a>
XHTML Spiele (ich nehme an, Sie XHTML verwenden?) Und einfach gilt Vorlagen für ihre Inhalt:
<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>
Dieses Sheet mit einer Situation umgehen wird, wo man etwas verschachtelt haben in das <a>
Element, das Sie behalten möchten, wie zum Beispiel:
<p>Here is <a href="....">some <em>linked</em> text</a>.</p>
, die Sie wollen kommen wie:
<p>Here is some <em>linked</em> text.</p>
Und es wird mit der Situation umgehen, wenn Sie den Link in einem unerwarteten Elemente zwischen dem üblichen Elternteil (das <p>
Element) und dem <a>
Elemente, wie verschachtelt haben:
<p>Here is <em>some <a href="...">linked</a> text</em>.</p>
Andere Tipps
Beispiel-Eingabedatei (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>
Stylesheet (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>
Ausführen mit xmlstarlet mit
xml tr collapse.xsl test.xml
Erzeugt:
<?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>
Die erste Vorlage im Stylesheet ist die grundlegende Identität Transformation (nur kopiert die ganze Ihr Eingabe-XML-Dokument). Die zweite Vorlage passt speziell auf die Elemente, die Sie ‚Zusammenbruch‘ wollen und nur Kopien der Tags und fügt den String-Wert des Elements (= Verkettung der Zeichenfolge-Wert von absteigenden Knoten).
In XSLT, könnten Sie einfach schreiben:
<xsl:template match="a"><a><xsl:apply-templates /></a></xsl:template>
<xsl:template match="a/b"><xsl:value-of select="."/></xsl:template>
Und du würdest erhalten:
<a>beforemiddleafter</a>
Wenn Sie also diesen den einfachen Weg machen wollen Sie nur einen XSL-Stylesheet erstellen könnten und Ihre XML-Datei durch, die ausgeführt werden.
Ich weiß, das ist nicht das, was Sie sagen, Sie tun möchten (mit Unix-Kommandozeile), jedoch. Ich weiß nichts über Unix, so vielleicht jemand anderes in die Lücken füllen, zB. eine Art Befehlszeile fordert, dass die oben ausführen kann.
Mit 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"
Haben Sie versucht das?
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>