Перемещение дочерних узлов узла XML вверх - PullRequest
1 голос
/ 24 сентября 2008

Представьте, что у меня есть свернутый XML-файл:

до средний после

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

beforemiddleafter

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

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

echo " до middle после " | xmlstarlet ed -m "// b / *" ".."

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

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

Ответы [ 5 ]

3 голосов
/ 24 сентября 2008

Пример входного файла (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-документ). Второй шаблон специально соответствует элементам, которые вы хотите «свернуть», и просто копирует теги и вставляет строковое значение элемента (= объединение строкового значения узлов-потомков).

2 голосов
/ 25 сентября 2008

Если вашей реальной целью является удаление ссылок с веб-страницы, то вам следует использовать такую ​​таблицу стилей, которая соответствует всем элементам 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>
2 голосов
/ 24 сентября 2008

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

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

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

1 голос
/ 04 июля 2010

Использование 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"
0 голосов
/ 24 сентября 2008

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

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...