Преобразование XML, где имя выходного элемента является динамическим?

#xml #xslt

#xml #xslt

Вопрос:

У меня есть XML, который мне нужно преобразовать в более упрощенный формат. Я уверен, что это можно сделать с помощью XSLT, но я не уверен, как.

Мне нужно преобразовать:

 <Fields>
  <Field>
    <Name>Element1</Name>
    <Value>Value 1</Value>
  </Field>
  <Field>
    <Name>Element2</Name>
    <Value>Value 2</Value>
  </Field>
</Fields>
  

в

 <Fields>
  <Element1>Value 1</Element1>
  <Element2>Value 2</Element2>
</Fields>
  

Это то, что у меня есть в настоящее время:

 <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="/*">
    <xsl:copy>
      <xsl:copy-of select="Fields/Field/*"/>
      <xsl:apply-templates select="*[name()]"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
  

Ответ №1:

Ваш входной XML,

 <Fields>
  <Field>
    <Name>Element1</Name>
    <Value>Value 1</Value>
  </Field>
  <Field>
    <Name>Element2</Name>
    <Value>Value 2</Value>
  </Field>
</Fields>
  

преобразовано этим XSLT,

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="Fields">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Field">
    <xsl:element name="{Name}">
      <xsl:value-of select="Value"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
  

выдает этот выходной XML,

 <?xml version="1.0" encoding="UTF-8"?>
<Fields>
  <Element1>Value 1</Element1>
  <Element2>Value 2</Element2>
</Fields>
  

как и было запрошено.

Комментарии:

1. Важное замечание: Существуют правила для допустимых имен элементов xml. (1) Имена не должны начинаться с цифры. (2) Имена не могут начинаться со специальных символов, таких как дефис или точка. (3) Имена не могут содержать специальных символов, кроме точки, дефиса, подчеркивания и двоеточия.

2. Вы можете предотвратить недопустимые имена до некоторой степени с помощью метода двойного перевода- <xsl:element name="{translate(Name, translate(Name, $validChars, ''), '')}"/> , где $validChars это переменная, содержащая все символы, которые вы хотите разрешить в имени. Хотя это немного грубо.