Базовое преобразование XML / XSLT: поиск и замена - PullRequest
2 голосов
/ 01 октября 2009

Я новичок в 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 ]

4 голосов
/ 01 октября 2009

У Джима Гаррисона будут удалены атрибуты любого элемента 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 соответственно.

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

Если ваш шаблон соответствует Customer, вы перехватываете всю обработку этого тега.

Попробуйте изменить шаблон так, чтобы он соответствовал только 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 соответственно.

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

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

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

<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>, как использовал Джим Гаррисон.

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