#xml #xslt
#xml #xslt
Вопрос:
Допустим, я очень плохо отформатировал XML, например:
<?xml version="1.0" encoding="ISO-8859-1"?>
<tag1>
<tag2>
Some text
</tag2>
<tag3>
Some other text
</tag3>
</tag1>
Я должен преобразовать его в форму, подобную:
<?xml version="1.0" encoding="ISO-8859-1"?>
<tag1>
<tag2>roman</tag2>
<tag3>Some other text</tag3>
</tag1>
Я пытался использовать преобразование XSLT подобным образом (также во многих вариантах):
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="text()">
<xsl:value-of select="normalize-space(.)" />
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
Я использовал этот онлайн-инструмент для проверки, но я всегда терплю неудачу…
Не могли бы вы помочь мне, какой самый простой способ сделать это?
Комментарии:
1. С вашим исходным XML-файлом все в порядке, но если вы хотите изменить его формат, вы можете попробовать использовать xmllint —format и указать XMLLINT_INDENT.
2. Мне скорее нужно более программируемое решение, поскольку эти XML-файлы являются своего рода протоколом между системами.
Ответ №1:
Причина, по которой ваша попытка не удалась, заключается в том, что у вас есть два шаблона, соответствующих текстовым узлам:
- ваш первый шаблон соответствует только текстовым узлам;
- ваши вторые шаблоны соответствуют узлам любого типа, включая текстовые узлы.
Большинство процессоров разрешают такой конфликт, применяя последний соответствующий шаблон в таблице стилей (хотя спецификация разрешает вместо этого сигнализировать об ошибке).
Простое решение состоит в том, чтобы изменить порядок шаблонов и надеяться, что процессор решит исправить ошибку.
В качестве альтернативы вы могли бы повысить приоритет первого шаблона выше -0,5 (приоритет шаблона преобразования идентификатора), например:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="text()" priority="0">
<xsl:value-of select="normalize-space(.)" />
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Чтобы получить результат, показанный в вашем вопросе, вы также захотите добавить:
<xsl:output indent="yes"/>
на верхнем уровне вашей таблицы стилей.
Комментарии:
1. Понятно! Большое вам спасибо!
Ответ №2:
Я не знаю, какой движок XSLT вы используете, но это работает для меня:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="normalize-space()"/>
</xsl:template>
</xsl:stylesheet>
Производит:
<?xml version="1.0"?><tag1><tag2>Some text</tag2><tag3>Some other text</tag3></tag1>
Посмотрите, как это работает здесь:https://xsltfiddle .liberty-development.net/ehW12ga