Как удалить разрывы строк в текстовых узлах xml

#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