#xml #xslt
#xml #xslt
Вопрос:
Это мой XML:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="test_2.xsl" type="text/xsl"?>
<doc xmlns="http://www.foo.org">
<div>
<title>Mr. Title</title>
<paragraph>This is one paragraph.
</paragraph>
<paragraph>Another paragraph.
</paragraph>
<list>
<orderedlist>
<item>
<paragraph>An item paragraph.</paragraph>
</item>
<item>
<paragraph>Another item paragraph</paragraph>
</item>
</orderedlist>
</list>
</div>
</doc>
Мой XML удаляет список, изменяет orderedlist на ol, изменяет item на li. Теперь я хотел бы избавиться от узлов абзаца, которые являются дочерними элементами элемента, при переносе текста в новый li. Обратите внимание, что я не хочу избавляться от узлов абзаца, которые НЕ являются дочерними элементами элемента.
Пока это мой XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foo="http://www.foo.org">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo:doc">
<xsl:element name="newdoc" namespace="http://www/w3.org/1999/xhtml">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="foo:div">
<segment title="{foo:title}">
<xsl:apply-templates/>
</segment>
</xsl:template>
<xsl:template match="foo:title">
<xsl:element name="h2">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="foo:paragraph">
<xsl:element name="p">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="foo:list">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="foo:orderedlist">
<xsl:element name="ol">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="foo:item">
<xsl:element name="li">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Результат такой:
<newdoc xmlns="http://www/w3.org/1999/xhtml">
<segment xmlns="" title="Mr. Title">
<h2>Mr. Title</h2>
<p>This is one paragraph.
</p>
<p>Another paragraph.
</p>
<ol>
<li>
<p>An item paragraph.</p>
</li>
<li>
<p>Another item paragraph</p>
</li>
</ol>
</segment>
</newdoc>
Бонус: я также хотел бы избавиться от пустых строк и исправить странное форматирование, вызванное удалением узла списка с
<xsl:template match="foo:list">
<xsl:apply-templates/>
</xsl:template>
итак, если кто-нибудь знает лучший способ удаления узла, я хотел бы это услышать.
Большое спасибо!
Ответ №1:
Просто добавьте более конкретное правило для абзацев, которые являются дочерними элементами списков:
<xsl:template match="foo:item/foo:paragraph">
<xsl:apply-templates/>
</xsl:template>
То же самое относится и к вашему дополнительному вопросу, если я правильно понимаю вопрос: не копируйте текстовые узлы с чистыми пробелами, которые являются дочерними элементами элементов списка.
<xsl:template match="foo:item/text()[normalize-space(.)='']" />
Комментарии:
1. Я ценю помощь, но я не могу заставить ни один из них работать. Я заменил свой шаблон match =»foo:list» на эту строку, и <список> снова появляется в выходных данных. Я также надеялся скопировать содержимое абзаца в <li> . И match=»foo: list / foo: paragraph», похоже, по какой-то причине ничего не находит / не делает.
2. Пожалуйста, не заменяйте ни один из ваших существующих кодов, просто добавьте новые правила.
3. Ну ладно! Тогда строка с нормализованным пробелом удаляет лишнюю строку. Замечательно. Хотя это не исправляет отступ — есть ли лучший способ удалить элемент, чем то, что я сделал? И match=»foo: item/ foo:paragraph» теперь находит узел, мне просто нужно было изменить list на item. Спасибо!!
4. Если вы не хотите, чтобы текстовые узлы с пробелами копировались в ваш вывод, вы должны явно отфильтровать их, так же, как последний фрагмент делает для тех, кто находится непосредственно внутри
foo:item
.
Ответ №2:
Эта таблица стилей:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foo="http://www.foo.org"
xmlns="http://www/w3.org/1999/xhtml"
exclude-result-prefixes="foo">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:preserve-space elements="foo:paragraph"/>
<xsl:template match="foo:doc">
<newdoc>
<xsl:apply-templates/>
</newdoc>
</xsl:template>
<xsl:template match="foo:div">
<segment title="{foo:title}">
<xsl:apply-templates/>
</segment>
</xsl:template>
<xsl:template match="foo:title">
<h2>
<xsl:apply-templates/>
</h2>
</xsl:template>
<xsl:template match="foo:paragraph">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="foo:orderedlist">
<ol>
<xsl:apply-templates/>
</ol>
</xsl:template>
<xsl:template match="foo:item">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
<xsl:template match="foo:item/foo:paragraph">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Вывод:
<newdoc xmlns="http://www/w3.org/1999/xhtml">
<segment title="Mr. Title">
<h2>Mr. Title</h2>
<p>This is one paragraph. </p>
<p>Another paragraph. </p>
<ol>
<li>An item paragraph.</li>
<li>Another item paragraph</li>
</ol>
</segment>
</newdoc>
Примечание: В настоящее время ваша таблица стилей представляет собой беспорядок пространств имен. Используйте @exclude-result-prefixes
. Исправьте пробелы только в текстовых узлах через объявления xsl:strip-space
и xsl:preserve-space
.