XSLT - цикл по элементам и преобразование в HTML - PullRequest
0 голосов
/ 21 ноября 2018

Мой вопрос - пройти через XML-файл, найти элементы, упомянутые в переменной 1, и заменить их на элементы в переменной 2, используя самый простой метод.

Пример XML

Ниже приведен пример файла XML:

 <?xml version="1.0" encoding="utf-8"?>
    <root>
    <figure id="f0005">
        <label>Fig. 1</label>
        <caption id="cn0005">
            <simple-para id="sp0015">Schematic diagram of the experimental setup.</simple-para>
        </caption>
    </figure>
    <figure id="f0010">
        <label>Fig. 2</label>
        <caption id="cn0010">
            <simple-para id="sp0020">Schematic drawing of the orifice plate.</simple-para>
        </caption>
    </figure>
</root>

Используя этот метод, я могу получить вывод.Но не тот, который указан в требуемом заголовке вывода.Я думаю, что я делаю что-то не так в цикле for в таблице стилей.Пожалуйста, поделитесь своими мыслями.

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="3.0">
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:variable name="els_element_name"
        select="tokenize('label simple-para figure caption', '\s+')"/>
    <xsl:variable name="html_element_name"
        select="tokenize('div div div div div', '\s+')"/>
    <xsl:template match="/">

        <xsl:for-each select="//element()"> 
            <xsl:variable name="ele_name" select="name()"/>
            <xsl:if test="index-of($els_element_name, $ele_name)">

                <xsl:variable name="array_val">
                    <xsl:value-of select="index-of($els_element_name, $ele_name)"/>
                </xsl:variable>

                <xsl:call-template name="optimized_code_start">
                    <xsl:with-param name="els_element" select="$ele_name"/>
                    <xsl:with-param name="position" select="$array_val"/>
                </xsl:call-template>

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

                <xsl:call-template name="optimized_code_end">
                    <xsl:with-param name="els_element" select="$ele_name"/>
                    <xsl:with-param name="position" select="$array_val"/>
                </xsl:call-template>

            </xsl:if>

        </xsl:for-each>


    </xsl:template>



    <xsl:template name="optimized_code_start">
        <xsl:param name="els_element"/>
        <xsl:param name="position" as="xs:integer"/>
        <xsl:text disable-output-escaping="yes">&lt;</xsl:text>
        <xsl:value-of select="$html_element_name[$position]"/>
        <xsl:text disable-output-escaping="yes"> class="</xsl:text>
        <xsl:value-of select="$els_element"/>
        <xsl:text disable-output-escaping="yes">"</xsl:text>
        <xsl:for-each select="@*[(name()='id')]">
            <xsl:text disable-output-escaping="yes"> </xsl:text>
            <xsl:value-of select="name()"/>
            <xsl:text disable-output-escaping="yes">="</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text disable-output-escaping="yes">"</xsl:text>
        </xsl:for-each>
        <xsl:for-each select="@*[not(name()='id')]">
            <xsl:choose>
                <xsl:when test="name() = 'xml:lang'">
                    <xsl:text disable-output-escaping="yes"> </xsl:text>
                    <xsl:value-of select="name()"/>
                    <xsl:text disable-output-escaping="yes">="</xsl:text>
                    <xsl:value-of select="."/>
                    <xsl:text disable-output-escaping="yes">"</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text disable-output-escaping="yes"> data-</xsl:text>
                    <xsl:value-of select="name()"/>
                    <xsl:text disable-output-escaping="yes">="</xsl:text>
                    <xsl:value-of select="."/>
                    <xsl:text disable-output-escaping="yes">"</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
        <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
    </xsl:template>


    <xsl:template name="optimized_code_end">
        <xsl:param name="els_element"/>
        <xsl:param name="position" as="xs:integer"/>
        <xsl:text disable-output-escaping="yes">&lt;/</xsl:text>
        <xsl:value-of select="$html_element_name[$position]"/>
        <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

Требуемый вывод

Я хотел бы получить вывод, как указано ниже.

    <html>
    <div class="figure" id="f0005">
    <div class="label">Fig. 1</div>
    <div class="caption" id="cn0005">
    <div class="simple-para" id="sp0015">Schematic diagram of the experimental setup.</div>
     </div>
    </div>
    <div class="figure" id="f0010">
    <div class="label">Fig. 2</div>
    <div class="caption" id="cn0010">
    <div class="simple-para" id="sp0020">Schematic drawing of the orifice plate. 
    </div>
    </div>
   </div>
   </html>

1 Ответ

0 голосов
/ 21 ноября 2018

Вы можете просто использовать index-of и xsl:element для сопоставления, а также сопоставлять имена входов с именами выходов:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

   <xsl:variable name="els_element_name"
        select="tokenize('label simple-para figure caption', '\s+')"/>
    <xsl:variable name="html_element_name"
        select="tokenize('div div div div div', '\s+')"/>

  <xsl:template match="*[index-of($els_element_name, name()) > 0]">
      <xsl:element name="{$html_element_name[index-of($els_element_name, name(current()))]}">
          <xsl:apply-templates select="@*"/>
          <xsl:attribute name="class" select="name()"/>
          <xsl:apply-templates/>
      </xsl:element>
  </xsl:template>  
</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / bdxtra / 2

Другой возможный подход может состоять в том, чтобы создать таблицу стилей, реализующую отображение, и запустить ее в XSLT 3.0 напрямую с помощью функции transform:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:axsl="http://www.w3.org/1999/XSL/Transform-alias"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

  <xsl:variable name="stylesheet">
      <axsl:stylesheet version="3.0">
          <axsl:mode on-no-match="shallow-copy"/>
          <xsl:for-each select="$els_element_name">
              <axsl:template match="{.}">
                  <axsl:element name="{let $p := position() return $html_element_name[$p]}">
                      <axsl:apply-templates select="@*"/>
                      <axsl:attribute name="class" select="'{.}'"/>
                      <axsl:apply-templates/>
                  </axsl:element>
              </axsl:template>
          </xsl:for-each>
      </axsl:stylesheet>
  </xsl:variable>

  <xsl:variable name="els_element_name"
        select="tokenize('label simple-para figure caption', '\s+')"/>
  <xsl:variable name="html_element_name"
        select="tokenize('div div div div div', '\s+')"/>

  <xsl:output indent="yes"/>

  <xsl:template match="/">
      <xsl:sequence select="$stylesheet"/>
      <xsl:sequence
        select="transform(
                  map {
                    'stylesheet-node' : $stylesheet,
                    'source-node' : .
                  }
                )?output"/>
  </xsl:template> 

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bdxtra/4.Для реального случая использования удалите или закомментируйте строку <xsl:sequence select="$stylesheet"/>, но я сохранил ее, чтобы показать созданную таблицу стилей.

...