2010-07-28 2 views
2

У меня есть следующий XML-документ:XSLT несколько узлов же имя же уровня

<ReportParameters SP="prRptActivityDetail"> 
    <Parameter> 
     <Name>Period Start Date</Name> 
     <Type>Date</Type> 
     <Control>DateTextbox</Control> 
     <ControlName>dtePeriodStartDate</ControlName> 
     <Validators> 
      <Validator>Required</Validator> 
      <Validator>DataTypeCheck</Validator> 
      <Validator>StartBeforeEnd</Validator> 
     </Validators> 
    </Parameter> 
</ReportParameters> 

Я написал файл XSLT для преобразования выше:

<xsl:for-each select="ReportParameters/Parameter/Validators"> 
    <xsl:choose> 
     <xsl:when test="Validator='Required'"> 
      <span> 
       <REQUIRED VALIDATOR CONTROL HERE> 
      </span> 
     </xsl:when> 
     <xsl:when test="Validator='DataTypeCheck'"> 
      <span> 
       <DATA TYPE CHECK VALIDATOR CONTROL HERE> 
      </span> 
     </xsl:when> 
    </xsl:choose> 

Я оставил вне много XSLT для ясности.

Для каждого управления параметрами (в этом случае в качестве даты начала периода) я хочу, чтобы все перечисленные валидаторы (3 в этом случае) были помещены на страницу в качестве элементов проверки правильности, но я получаю только первый, каждый. Я знаю, почему это так, но я полный новичок с xslt и не знаю синтаксиса, чтобы обойти это.

Любая помощь с оценкой,

Богатый.

+0

Хороший вопрос (+1).См. Мой ответ для полностью «беззаботного» решения, которое полностью находится в стиле «push-style» и в духе языка XSLT. :) –

ответ

1

Я предлагаю заменить ваш <xsl:for-each тег:

<xsl:apply-templates select="ReportParameters/Parameter/Validators/Validator" />

и включают в себя шаблоны для каждого:

<xsl:template match="Validator[text()='Required']"> 
    ... 
</xsl:template> 

<xsl:template match="Validator[text()='DataTypeCheck']"> 
    .. 
</xsl:template> 

etc. 

Как сказал @kniemczak, вы на самом деле только циклических через родительский элемент на данный момент.

+0

Я пошел с этим решением, поскольку оно соответствовало моим потребностям, но все ответы помогли мне. –

2

Я думаю, проблема в том, что вы перебираете коллекцию «Validators». Вы хотите перебрать все экземпляры «Validator».

Try: (example I used in research)

<xsl:for-each select="ReportParameters/Parameter/Validators/Validator"> 
    <xsl:choose> 
     <xsl:when test=".='Required'"> 
      <span> 
       <REQUIRED VALIDATOR CONTROL HERE> 
      </span> 
     </xsl:when> 
     <xsl:when test=".='DataTypeCheck'"> 
      <span> 
       <DATA TYPE CHECK VALIDATOR CONTROL HERE> 
      </span> 
     </xsl:when> 
    </xsl:choose> 
0

Для такого рода задачи вам не нужно явно перебирает элементы. Это не способ XSLT. Подумайте больше о сопоставлении с древовидной структурой.

Что-то, как это будет работать:

<xsl:if test="ReportParameters/Parameter/Validators/Validator='Required'"> 
    <span> 
     <REQUIRED></REQUIRED> 
    </span> 
</xsl:if> 
<xsl:if test="ReportParameters/Parameter/Validators/Validator='DataTypeCheck'"> 
    <span> 
     <DATA></DATA> 
    </span> 
</xsl:if> 

Также смотрите на создание суб <xsl:template> с и призывая их <xsl:apply-templates> обрабатывать меньшие части дерева. Для большого преобразования он должен быть намного более удобным.

+0

Спасибо большое всем - я пошел с шаблоном решения. –

1

При изучении XSLT хорошо знать, что следует избегать использования <xsl:for-each>, если это действительно не необходимо.

Вот простой и короткий «loopless» путь добиться того же в чистом нажимной стиле:

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

<xsl:variable name="vrtfValidatorNames"> 
    <validator type="Required" name="REQUIRED"/> 
    <validator type="DataTypeCheck" name="DATA TYPE CHECK"/> 
    <validator type="StartBeforeEnd" name="START BEFORE END"/> 
</xsl:variable> 

<xsl:variable name="vValidatorNames" select= 
    "document('')/*/xsl:variable[@name='vrtfValidatorNames']/*"/> 

<xsl:template match="Validator"> 
    &lt;<xsl:value-of select="$vValidatorNames[@type=current()]/@name"/> VALIDATOR CONTROL HERE> 
</xsl:template> 

<xsl:template match="text()"/> 
</xsl:stylesheet> 

, когда это преобразование применяется на поставленном XML документа:

<ReportParameters SP="prRptActivityDetail"> 
    <Parameter> 
     <Name>Period Start Date</Name> 
     <Type>Date</Type> 
     <Control>DateTextbox</Control> 
     <ControlName>dtePeriodStartDate</ControlName> 
     <Validators> 
      <Validator>Required</Validator> 
      <Validator>DataTypeCheck</Validator> 
      <Validator>StartBeforeEnd</Validator> 
     </Validators> 
    </Parameter> 
</ReportParameters> 

получен желаемый результат:

<REQUIRED VALIDATOR CONTROL HERE> 

    <DATA TYPE CHECK VALIDATOR CONTROL HERE> 

    <START BEFORE END VALIDATOR CONTROL HERE> 
+0

+1 для элегантного решения. Но для того, чтобы узнать XSLT, было бы хорошим объяснением, почему его трансформация не работает. Все остальные ответят пятно контекстного узла внутри 'for-each', что является неправильным объяснением предоставленного фрагмента XSLT. – 2010-07-28 13:34:59

+0

@ Alejandro: Я согласен, но я считаю более важным дать понять новичкам, что в XSLT '' и push-style - это действительно важные вещи, а не '' –

Смежные вопросы