2009-09-30 3 views
2

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

Общая цель этого упражнения - заменить значения «Y» и «N» в элементе «NewCustomer» на «true» или «false» соответственно.

Вот мои данные образца.

<?xml version="1.0"?> 
<CustomerList> 
    <Customer> 
    <CustomerID>1111</CustomerID> 
    <CompanyName>Sean Chai</CompanyName> 
    <City>New York</City> 
    <NewCustomer>N</NewCustomer> 
    </Customer> 
    <Customer> 
    <CustomerID>1112</CustomerID> 
    <CompanyName>Tom Johnston</CompanyName> 
    <City>Los Angeles</City> 
    <NewCustomer>N</NewCustomer> 
    </Customer> 
    <Customer> 
    <CustomerID>1113</CustomerID> 
    <CompanyName>Institute of Art</CompanyName> 
    <City>Chicago</City> 
    <NewCustomer>Y</NewCustomer> 
    </Customer> 
</CustomerList> 

Вот таблица стилей трансформации.

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

    <!-- Identity Template (applies to all nodes and will copy all nodes --> 
    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Customer"> 
    <xsl:choose> 
     <xsl:when test="NewCustomer = 'Y'"> 
     <xsl:text>true</xsl:text> 
     </xsl:when> 
     <xsl:when test="NewCustomer = 'N'"> 
     <xsl:text>false</xsl:text> 
     </xsl:when> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

Вот мой вывод.

<?xml version="1.0" encoding="utf-8" ?> 
    <CustomerList>false false true</CustomerList> 

Вот что я хочу, чтобы он выводил.

<?xml version="1.0"?> 
<CustomerList> 
    <Customer> 
    <CustomerID>1111</CustomerID> 
    <CompanyName>Sean Chai</CompanyName> 
    <City>New York</City> 
    <NewCustomer>false</NewCustomer> 
    </Customer> 
    <Customer> 
    <CustomerID>1112</CustomerID> 
    <CompanyName>Tom Johnston</CompanyName> 
    <City>Los Angeles</City> 
    <NewCustomer>false</NewCustomer> 
    </Customer> 
    <Customer> 
    <CustomerID>1113</CustomerID> 
    <CompanyName>Institute of Art</CompanyName> 
    <City>Chicago</City> 
    <NewCustomer>true</NewCustomer> 
    </Customer> 
</CustomerList> 

Что мне не хватает и почему? Я вижу, что если я опустил пункты, где я исследую NewCustomer, весь вывод будет выводиться. Тем не менее, выбирая вывод правильно измененных значений для результатов NewCustomer, отображаются только их отображаемые. Есть ли ссылка на предыдущий шаблон, который я должен сделать во втором шаблоне?

ответ

3

Имея свой шаблонный совпадение с Клиентом, вы перехватываете всю обработку для этого тега.

Попробуйте изменить шаблон только для соответствия NewCustomer, внеся соответствующие изменения в условия тестирования (test = ". = 'Y').

Также обратите внимание, что вам необходимо создать тег NewCustomer в выходном файле, поскольку, сопоставляя его в пользовательском шаблоне, он не обрабатывается преобразованием идентичности. Ты очень близко.

Вот обновленный шаблон:

<xsl:template match="Customer/NewCustomer"> 
    <xsl:copy> 
     <xsl:choose> 
      <xsl:when test=". = 'Y'"> 
       <xsl:text>true</xsl:text> 
      </xsl:when> 
      <xsl:when test=". = 'N'"> 
       <xsl:text>false</xsl:text> 
      </xsl:when> 
     </xsl:choose> 
    </xsl:copy> 
</xsl:template> 

Во-первых, он совпадает с NewCustomer ребенком Клиента. Затем он использует xsl: copy для создания копии узла (но не атрибутов или дочерних элементов). Затем он использует ваш xsl: выберите для преобразования значений N и Y в значение false и true соответственно.

Основная концепция заключается в том, что когда шаблон соответствует входному элементу, элемент ввода эффективно удаляется из вывода и заменяется содержимым соответствующего шаблона. В вашем случае, когда вы соответствовали клиенту, тег Customer и все внутри него были заменены содержимым шаблона, который только что сгенерировал «true» или «false».

+1

Хорошее объяснение, +1. – Tomalak

+0

+1 для эффективного ответа на вопрос о том, почему часть вопроса. – GuruM

0

Хорошее объяснение в ответе Джима Гаррисона по-прежнему применяется. Вот сгущенное/альтернативный подход:

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

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:choose> 
     <xsl:when test="self::NewCustomer"> 
      <xsl:value-of select="boolean(number(translate(., 'YN', '10')))" /> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

Выражение boolean(number(translate(., 'YN', '10'))) изменяет 'Y' к '1' и 'N' к '0', который затем преобразуется в первый ряд, а затем в булево значение. Булев будет представлен как 'true' или 'false', соответственно.

Это немного грязный, так как он на самом деле не справиться, кроме 'Y' или 'N' значения - но он будет выводить 'false' для любого значения, кроме 'Y'.

Это просто пространство-хранитель. Если вы хотите, вы можете заменить его на <xsl:choose>, как и использовал Джим Гаррисон.

4

Джим Гаррисон снимает атрибуты с любого элемента NewCustomer, который имеет их. И Томалак, как он выразился, немного грязный.

Эта версия является почти дословным переводом вашего требования в XSLT:

<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="NewCustomer/text()[.='Y']"> 
    <xsl:text>true</xsl:text> 
    </xsl:template> 

<xsl:template match="NewCustomer/text()[.='N']"> 
    <xsl:text>false</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 

Единственные узлы в исходном дереве, что он не копирует точно в набор результатов являются текстовыми узлами, которые являются потомками NewCustomer элементы и значение которых равно Y или N; для них он испускает соответственно true и false.

+0

+1 Есть действительно много способов решить эту задачу. Я «предположил» схему из данных данных и не стал копировать атрибуты. –

+0

См. Ответ @JimGarrison для вопроса «как/почему». – GuruM