Добавление узла в другой в XSLT - PullRequest
1 голос
/ 09 октября 2009

У меня есть xml вот так:

  <configurationData>
    <path name='b'>
      <path name='a'>
        <setting name='s1'>
        ![CDATA[XXXX]]
        </setting>
        <setting name='s2'>
          XXXX
        </setting>
      </path>
    </path>
  </configurationData>

, где configurationData - корневой узел, и могут быть вложенные пути, за которыми следует один или несколько узлов настройки. Я хочу преобразовать узел настройки, чтобы поместить содержимое узла настройки в дочерний узел с именем value

  <configurationData>
    <path name='b'>
      <path name='a'>
        <setting name='s1'>
          <value>![CDATA[XXXX]]</value>
        </setting>
        <setting name='s2'>
          <value>XXXX</value>
        </setting>
      </path>
    </path>
  </configurationData>

Я должен признать, что нахожу XML умственным препятствием и не могу понять, какой XSLT использовать:

Это моя попытка:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output encoding ="utf-8" indent="yes" method="xml" version="1.0"/>

  <xsl:template match='/setting'>
    <xsl:apply-templates select='setting' />
  </xsl:template>

  <xsl:template match='setting'>
    <value>
      <xsl:value-of select='.'/>
    </value>
  </xsl:template>
</xsl:stylesheet>

Ответы [ 2 ]

3 голосов
/ 09 октября 2009

Вы на 90% пути туда. Что вам нужно, это «шаблон личности»

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output encoding ="utf-8" indent="yes" method="xml" version="1.0"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match='setting'>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <value>
                <xsl:value-of select='.'/>
            </value>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Первый шаблон обрабатывает все узлы, копируя их в выходные данные. Однако шаблон «настройки», будучи более конкретным, вызывается для «настроек» узлов. Этот шаблон копирует сам узел и его атрибуты, а затем оборачивает значение в тег «значения».

Самым неинтуитивным в XSLT является то, что таблица стилей не является программой, которая управляет процессом. Вместо этого управляет входной XML-документ, а таблица стилей содержит инструкции, которые выбираются и выполняются в соответствии с тем, что находится во входных данных. Это называется «принудительной» обработкой. XSL-процессор передает данные в вашу таблицу стилей. XSLT имеет некоторые процедурные возможности, и вы можете написать таблицу стилей в стиле «тянуть», где таблица стилей пытается управлять процессом, но это сложнее и приводит к сложным в обслуживании таблицам стилей.

Edit: Для включения разделов CDATA замените:

<xsl:value-of select='.' />

с

![CDATA[<xsl:value-of select='.' disable-output-escaping="yes"/>]]

(хотя это и не лучшее решение, поскольку оно всегда добавляет CDATA)

0 голосов
/ 09 октября 2009

Мое предложение, основанное на ответе Джима Гаррисона:

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="xml" encoding="utf-8" cdata-section-elements="value" />

  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="setting/text()">
    <value>
      <xsl:value-of select="." />
    </value>
  </xsl:template>

</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...