Pergunta

Imagine que eu tenha o arquivo XML folling:

antes Médio após

Eu quero convertê-lo em algo como isto:

beforemiddleafter

Em outras palavras eu quero começar todos os nós do filho de um determinado nó, e movê-los para o nó pai em ordem. Isso é como fazer este comando: ". Mv ./directory/*", mas para nós XML

Eu gostaria de fazer isso em usar ferramentas de linha de comando do Unix. Eu tenho tentado com xmlstarlet, que é uma poderosa linha de comando manipulador XML. Eu tentei fazer algo parecido com isso, mas ele não funciona

echo " antes Médio após " | xmlstarlet ed -m "// b / *" ".."

Update:. Modelos XSLT são bons, uma vez que podem ser chamados a partir da linha de comando

Meu objetivo aqui é 'remover os links de uma página XHTML', em outras palavras, substituir onde o link foi, com o conteúdo da tag link.

Foi útil?

Solução

Se o seu objetivo real é para remover os links de uma página web, então você deve usar uma folha de estilo como este, que corresponde a todos os elementos XHTML <a> (eu estou supondo que você está usando XHTML?) E simplesmente aplica modelos para a sua conteúdo:

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

Este estilo vai lidar com uma situação onde você tem algo aninhados em o elemento <a> que pretende manter, tais como:

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

que você vai querer sair como:

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

E vai lidar com a situação onde você tem o link aninhada dentro de um elemento inesperado entre o pai de costume (o elemento <p>) eo elemento <a>, tais como:

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

Outras dicas

arquivo de entrada Exemplo (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>

folha de estilo 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>

Executar com xmlstarlet usando

xml tr collapse.xsl test.xml

Produz:

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

O primeiro modelo na folha de estilo é a transformação identidade básica (apenas copia todo o seu documento XML de entrada). O segundo modelo corresponde especificamente os elementos que deseja 'colapso' e copia apenas as tags e insere o valor string do elemento (= concatenação da cadeia de valor de nós descendentes).

Em XSLT, você poderia simplesmente escrever:

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

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

E você deseja obter:

<a>beforemiddleafter</a>

Então, se você queria fazer isso da maneira mais fácil você poderia simplesmente criar uma folha de estilo XSL e executar o arquivo XML por isso.

Sei que isso não é o que você disse que gostaria de fazer (usando linha de comando Unix), no entanto. Eu não sei nada sobre Unix, então talvez alguém pode preencher os espaços em branco, por exemplo. algum tipo de chamadas de linha de comando que pode executar o acima.

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

Você já tentou isso?

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top