Перемещение дочерних узлов узла XML вверх


1

Представьте меня есть феллинг XML файл:

< > перед тем < б > средний </б > после </а >

Я хочу, чтобы преобразовать его во что-то вроде этого:

< > beforemiddleafter </с >

Другими словами, я хочу получить все дочерние узлы определенного узла и привести их в исходный узел по порядку. Это похоже на выполнение этой команды: «mv ./directory/*.», Но для узлов xml.

Я хотел бы сделать это с помощью инструментов командной строки unix. Я пытался с xmlstarlet, который является мощным манипулятором XML-манипулятора. Я пытался делать что-то вроде этого, но он не работает

эхо «< > перед тем < б > средний </б > после </а >» | xmlstarlet ed -m "// b/*" ".."

Обновление: XSLT-шаблоны прекрасны, поскольку их можно вызвать из командной строки.

Моя цель здесь «удалить ссылки с страницы XHTML», другими словами заменить место ссылки, с содержимым тега ссылки.

2

Если фактическая цель состоит в том, чтобы удалить ссылки с веб-страницы, то вы должны использовать таблицу стилей, как это , который соответствует всем XHTML <a> элементы (я предполагаю, что вы используете XHTML?) И просто применяет шаблоны для их содержания:

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

Эта таблица стилей будет иметь дело с ситуацией, когда вы что-то вложенной в в <a> элемент, который вы хотите сохранить, такие как:

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

, который вы хотите, чтобы выйти, как:

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

И он будет иметь дело с ситуацией, когда у вас есть ссылка, вложенные в неожиданном элементе между обычным родителем (<p> элемента) и <a> элементом, такими как:

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

Это именно то, что я искал. Спасибо за подробный ответ, объясняющий, как все это работает 25 сен. 082008-09-25 13:14:22


2

В XSLT, вы могли бы просто написать:

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

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

И вы получите:

<a>beforemiddleafter</a> 

Так что, если вы хотите сделать это легкий путь вы можете просто создать таблицу стилей и запустите XML-файл.

Я понимаю, что это не то, что вы сказали, что хотите сделать (используя командную строку Unix). Я ничего не знаю об Unix, так что, возможно, кто-то может заполнить пробелы, например. некоторые вызовы командной строки, которые могут выполнять вышеуказанные действия.


3

Пример входного файла (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> 

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> 

Запуск с использованием XMLStarlet

xml tr collapse.xsl test.xml 

Выдает:

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

Первый шаблон в таблице стилей - это основное преобразование идентичности (просто копирует весь ваш XML-документ ввода). Второй шаблон специально соответствует элементам, которые вы хотите «свернуть», и просто копирует теги и вставляет строковое значение элемента (= конкатенация строкового значения узлов-потомков).


0

Вы пробовали это?

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> 

1

Использованием XMLStarlet:

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