Pregunta

Imagine que tiene la folling archivo XML:

<a>antes de la<b>media</b>después de</a>

Quiero convertirlo en algo como esto:

<a>beforemiddleafter</a>

En otras palabras, se desea obtener todos los nodos hijos de un nodo determinado, y los mueve al nodo padre en orden.Esto es como hacer este comando:"mv ./directorio/* .", pero para los nodos xml.

Me gustaría hacerlo en el uso de unix herramientas de línea de comandos.He estado tratando con xmlstarlet, que es una potente línea de comandos XML de manipulador.He intentado hacer algo como esto, pero no funciona

echo "<a>antes de la<b>media</b>después de</a>" | xmlstarlet ed -m "//b/*" ".."

Actualización:Plantillas XSLT están bien, ya que puede ser llamado desde la línea de comandos.

Mi objetivo aquí es 'quitar los enlaces de una página XHTML', en otras palabras reemplazar donde estaba el enlace, con el contenido de la etiqueta de enlace.

¿Fue útil?

Solución

Si su objetivo es eliminar los enlaces de una página web, entonces usted debe utilizar una hoja de estilo como este, que coincide con todos XHTML <a> elementos (estoy asumiendo que usted está utilizando XHTML?) y simplemente se aplica plantillas a su contenido:

<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>

Esta hoja de estilos que lidiar con una situación en la que usted tiene algo anidados dentro de el <a> elemento que desea conservar, tales como:

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

que usted va a querer salir a la luz:

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

Y va a lidiar con la situación en la que tienes el enlace anidado dentro de un elemento inesperado entre los habituales de los padres (la <p> elemento) y el <a> elemento, tales como:

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

Otros consejos

Ejemplo de archivo de entrada (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>

La hoja de estilo XSLT (colapso.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>

Ejecutar con XmlStarlet el uso de

xml tr collapse.xsl test.xml

Produce:

<?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>

La primera plantilla en la hoja de estilos es el de la identidad básica de la transformación (sólo copias de la totalidad de su documento XML de entrada).La plantilla de la segunda específicamente coincide con los elementos que desea 'colapso' y copias de las etiquetas y carátulas de la cadena de valor del elemento (=concatenación de la cadena de valor de los nodos descendientes).

En XSLT, puede escribir:

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

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

Y que te dan:

<a>beforemiddleafter</a>

Así que si usted quería hacer esto de la manera más fácil simplemente puede crear una hoja de estilo XSL y ejecutar el archivo XML a través de eso.

Me doy cuenta de que esto no es lo que usted dijo que le gustaría hacer (usando la línea de comandos de Unix), sin embargo.No sé nada acerca de Unix, así que tal vez alguien más puede llenar los espacios en blanco, por ejemplo.algún tipo de línea de comandos de llamadas que se pueden ejecutar los anteriores.

El uso 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"

¿Has probado esto?

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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top