Как выбрать несколько узлов в одном для каждого в XSLT - PullRequest
6 голосов
/ 05 мая 2010

Я пытаюсь выучить XSLT, но лучше всего работаю на примере. Я хочу выполнить тривиальное преобразование схемы в схему. Как выполнить это преобразование всего за один проход (мое текущее решение использует два прохода и теряет первоначальный заказ клиентов)?

От:

<?xml version="1.0" encoding="UTF-8"?>
<sampleroot>

<badcustomer>
    <name>Donald</name>
    <address>Hong Kong</address>
    <age>72</age>
</badcustomer>

<goodcustomer>
    <name>Jim</name>
    <address>Wales</address>
    <age>22</age>
</goodcustomer>

<goodcustomer>
    <name>Albert</name>
    <address>France</address>
    <age>51</age>
</goodcustomer>

</sampleroot>

Кому:

<?xml version="1.0" encoding="UTF-8"?>
<records>

<record id="customer">
    <name>Donald</name>
    <address>Hong Kong</address>
    <age>72</age>
    <customertype>bad</customertype>
</record>

<record id="customer">
    <name>Jim</name>
    <address>Wales</address>
    <age>22</age>
    <customertype>good</customertype>
</record>

<record id="customer">
    <name>Albert</name>
    <address>France</address>
    <age>51</age>
    <customertype>good</customertype>
</record>

</records>

Я уже решил эту проблему плохо (я теряю заказ клиентов и считаю, что мне нужно проанализировать файл несколько раз:

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/sampleroot">

    <records>

        <xsl:for-each select="goodcustomer">
            <record id="customer">
                <name><xsl:value-of select="name" /></name>
                <address><xsl:value-of select="address" /></address>
                <age><xsl:value-of select="age" /></age>
                <customertype>good</customertype>
            </record>
        </xsl:for-each>

        <xsl:for-each select="badcustomer">
            <record id="customer">
                <name><xsl:value-of select="name" /></name>
                <address><xsl:value-of select="address" /></address>
                <age><xsl:value-of select="age" /></age>
                <customertype>bad</customertype>
            </record>
        </xsl:for-each>

    </records>
    </xsl:template>
</xsl:stylesheet>

Может, кто-нибудь поможет мне с правильной конструкцией XSLT, где мне нужно использовать только один разбор (только один для каждого)?

Спасибо

Chris

1 Ответ

7 голосов
/ 05 мая 2010

Хорошая практика XSLT - избегать использования <xsl:for-each> в максимально возможной степени .

Вот простое решение, использующее этот принцип :

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

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

 <xsl:template match="/*">
  <records>
    <xsl:apply-templates/>
  </records>
 </xsl:template>

 <xsl:template match="badcustomer | goodcustomer">
  <record>
   <xsl:apply-templates/>
   <customertype>
     <xsl:value-of select="substring-before(name(), 'customer')"/>
   </customertype>
  </record>
 </xsl:template>
</xsl:stylesheet>

Примечание :

  1. Используются только шаблоны и <xsl:apply-templates>.

  2. Использование правила идентификации и его переопределения там, где это необходимо. Это один из самых фундаментальных шаблонов проектирования XSLT.

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