Проблема вставки узла (текста) в документ XML через XSLT - PullRequest
1 голос
/ 10 июня 2010

У меня возникают проблемы при вставке блока текста при выполнении определенного условия в документе xml с использованием XSLT. Предположим, у меня есть следующий xml:

<oldStep Name="Step1">
    <oldItems>
        <oldItem ItemName="item1">
        </oldItem>
        <!-- want to add an extra <Item> here if Step Name == "Step1" -->
        <oldItem ItemName="Step1item">
        </oldItem>
    </oldItems>
</oldStep>
<oldStep Name="Step2">
    <oldItems>
       ...
    </oldItems>
</oldStep>

Среди преобразования старых имен узлов в новые, я хочу добавить дополнительный блок текста (или созданный вручную узел) всякий раз, когда oldStep Name равно определенному значению (в данном случае, Step1). Я попытался использовать следующий XSLT, но в итоге получилось странное поведение при добавлении блока текста к каждому отдельному узлу (иногда даже не под узлом) в XML после его сопоставления. Кроме того, у меня возникают проблемы при пропуске узла, чтобы его можно было вставить в элементы, а не прямо под oldStep:

<xsl:template match="oldItems">
    <xsl:element name="Item">
        <xsl:if test="../@Name = 'Step1'>
            <xsl:call-template name = "identity"></xsl:call-template>
        </xsl:if>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="node()" name="identity">
    <xsl:element name="Item">
        <xsl:attribute name="ItemName">Step1item</xsl:attribute>
        </xsl:apply-templates />
    </xsl:element>
</xsl:template>

У меня такое ощущение, что я неправильно понял условия, но поиск в Google не очень помог (строка поиска слишком расплывчата). Чего мне не хватает в xsl? Или есть лучший подход к этой проблеме?

Спасибо.

Ответы [ 3 ]

1 голос
/ 10 июня 2010

Ваш шаблон с именем "identity" соответствует любому узлу, поэтому будет применять его для каждого обрабатываемого им узла. Не имей ничего подходящего.

1 голос
/ 10 июня 2010

Ваше описание немного сложно для подражания.Вот как я интерпретирую ваш вопрос:

Дайте мне преобразователь, который копирует все по умолчанию, кроме:

  • он преобразует элементы oldItem в элементы Item
  • он добавляетдополнительный элемент к элементу oldItems в «шаге 1» в качестве последнего элемента

И вот решение:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- by default, copy everything -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <!-- special handling for old items -->
  <xsl:template match="oldItems">
    <!-- transform all old items first -->
    <xsl:apply-templates select="@*|node()"/>
    <xsl:if test="../@Name = 'Step1'">
      <xsl:call-template name="add-new-step1-stuff"/>
    </xsl:if>
  </xsl:template>
  <!-- add new step 1 stuff -->
  <xsl:template name="add-new-step1-stuff">
    <xsl:element name="Item">
      <xsl:attribute name="ItemName">Step1item</xsl:attribute>
    </xsl:element>
  </xsl:template>
  <!-- converts each oldItem to Item -->
  <xsl:template match="oldItem"> 
    <xsl:element name="Item">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

, которое применительно к:

<?xml version="1.0" encoding="utf-8"?>
<oldSteps>
  <oldStep Name="Step1">
    <oldItems>
      <oldItem ItemName="item1"></oldItem>
    </oldItems>
  </oldStep>
  <oldStep Name="Step2">
    <oldItems>
      <oldItem ItemName="item2"></oldItem>
      <oldItem ItemName="item3"></oldItem>
    </oldItems>
  </oldStep>
</oldSteps>

(не совсем то, что вы дали, но то, что, как я думаю, вы хотели)

приводит к:

<?xml version="1.0"?>
<oldSteps>
  <oldStep Name="Step1">

      <Item ItemName="item1"/>
    <Item ItemName="Step1item"/>
  </oldStep>
  <oldStep Name="Step2">

      <Item ItemName="item2"/>
      <Item ItemName="item3"/>

  </oldStep>
</oldSteps>

, которая требует некоторой очистки пробелов, но я думаю, что это структура, которую выищите.

Если вы хотите заблокировать текст вместо дополнительного элемента, вы можете просто переписать шаблон add-new-step1-stuff следующим образом:

<!-- add new step 1 stuff -->
<xsl:template name="add-new-step1-stuff">
  <xsl:text>
    Here's some block text that goes at the end.
  </xsl:text>
</xsl:template>

Ключевые различия между моей таблицей стилей и вашей:

  • Ваше преобразование личности (копирование по умолчанию) применяется к каждому узлу в вашем документе и создает элемент, в который вы копируете остальное содержимое -вот почему вы видите предметы повсюду!В моем случае преобразование идентичности и добавление элемента разделены.Обратите внимание, что преобразование идентификаторов не нужно вызывать явно, если вы добавляете apply-templates в соответствующих местах.
  • В ваших преобразованиях отсутствует копирование атрибутов, которое, я полагаю, вы хотите сохранить вместо этого.
  • Ваша трансформация добавит Item после каждого oldItem в oldItems после шага 1, что, как я также представляю, не то, что вы хотите.
1 голос
/ 10 июня 2010

Это преобразование :

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

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

 <xsl:template match="oldStep[@Name='Step1']/*/oldItem[1]">
  <xsl:call-template name="identity"/>

  <Item ItemName='Step1item'/>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному XML-документу :

<steps>
    <oldStep Name="Step1">
        <oldItems>
            <oldItem ItemName="item1"/>
            <!-- want to add an extra <Item> here if Step Name == "Step1" -->
            <oldItem ItemName="Step1item"/>
        </oldItems>
    </oldStep>
    <oldStep Name="Step2">
        <oldItems>
       ...
        </oldItems>
    </oldStep>
</steps>

создает искомоерезультат :

<steps>
   <oldStep Name="Step1">
      <oldItems>
         <oldItem ItemName="item1"/>
         <Item ItemName="Step1item"/><!-- want to add an extra <Item> here if Step Name == "Step1" -->
         <oldItem ItemName="Step1item"/>
      </oldItems>
   </oldStep>
   <oldStep Name="Step2">
      <oldItems>
       ...
        </oldItems>
   </oldStep>
</steps>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...