2016-11-29 4 views
0

Я застреваю в цикле и нуждаюсь в каком-то направлении от группы. Я могу зациклиться на одном ребенке, но у меня проблемы с добавлением второго.XSLT Вложенная петля нескольких дочерних элементов

Это мой XML:

<wd:Report_Entry> 
    <wd:Beneficiaries_-_All> 
    <wd:EMPLID>00025</wd:EMPLID> 
    <wd:Last>LastName</wd:Last> 
    <wd:First>FirstName</wd:First> 
    <wd:WID>key1234</wd:WID> 
    </wd:Beneficiaries_-_All> 
    <wd:Beneficiaries_-_All> 
    <wd:EMPLID>00025</wd:EMPLID> 
    <wd:Last>LastName</wd:Last> 
    <wd:First>First2</wd:First> 
    <wd:WID>key4567</wd:WID> 
    </wd:Beneficiaries_-_All> 
    <wd:Beneficiaries_-_People> 
    <wd:DOB>Birth1</wd:DOB> 
    <wd:ID>ID1</wd:ID> 
    <wd:WID>key1234</wd:WID> 
    </wd:Beneficiaries_-_People> 
    <wd:Beneficiaries_-_People> 
    <wd:DOB>Birth2</wd:DOB> 
    <wd:ID>ID2</wd:ID> 
    <wd:WID>key4567</wd:WID> 
    </wd:Beneficiaries_-_People> 
</wd:Report_Entry> 

Мой XSLT ниже

<xsl:output method="text"/> 
<xsl:variable name="linefeed" select="'&#xA;'"></xsl:variable> 

<xsl:template match="/"> 
<xsl:for-each select="/wd:Report_Data/wd:Report_Entry"> 
    <xsl:for-each select="wd:Beneficiaries_-_All"> 
    <xsl:text>"</xsl:text> 
    <xsl:value-of select="wd:EMPLID"/> 
    <xsl:text>","</xsl:text> 
    <xsl:value-of select="wd:Last"/> 
    <xsl:text>","</xsl:text> 
    <xsl:value-of select="wd:First"/> 
    <xsl:text>","</xsl:text> 
    <xsl:value-of select="$linefeed"/> 
    </xsl:for-each> 
    <xsl:for-each select="wd:Beneficiaries_-_People"> 
    <xsl:value-of select="wd:DOB"/> 
    <xsl:text>","</xsl:text> 
    <xsl:value-of select="wd:ID"/> 
    <xsl:text>"</xsl:text> 
    </xsl:for-each> 
    <xsl:value-of select="$linefeed"/> 
</xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

Моя требуемый выход CSV так:

"00025", "LastName",» First1 "," Birth1 "," ID1 "
" 00025 "," LastName "," First2 "," Birth2 "," ID2 "
"00026", "LastName", "First1", "Birth1", "ID1" (продолжается таким образом)

Но я получаю для каждой записи Доклад:

"00025" , "LastName", "First1", "
"00025", "LastName", "First2","
Birth1" , "ID1" Birth2" , "ID2"

Мои исследования на этом сайте указывает, что <apply-templates> является предпочтительным по сравнению с <for-each>. Формат дает мне проблему, когда я пытаюсь использовать этот метод. Спасибо группе!

+0

Что связывает даты рождения с людьми? –

+0

В запросе, который создавал XML, метаданные бенефициара на «ВСЕ» и «Люди» имеют общий идентификатор . – BWatkins

+0

Боюсь, я не вижу такой вещи в приведенном примере. –

ответ

0

Если я правильно понимаю, нужно просто переменный, чтобы сделать его работу:

<xsl:for-each select="/wd:Report_Data/wd:Report_Entry"> 
    <xsl:for-each select="wd:Beneficiaries_-_All"> 
     <xsl:text>"</xsl:text> 
     <xsl:value-of select="wd:EMPLID"/> 
     <xsl:text>","</xsl:text> 
     <xsl:value-of select="wd:Last"/> 
     <xsl:text>","</xsl:text> 
     <xsl:value-of select="wd:First"/> 
     <xsl:text>","</xsl:text> 
     <!-- new code starts here --> 
     <xsl:variable name="WID" select="wd:WID"/> 
     <xsl:value-of select="../wd:Beneficiaries_-_People[wd:WID = $WID]/wd:DOB"/> 
     <xsl:text>","</xsl:text> 
     <xsl:value-of select="../wd:Beneficiaries_-_People[wd:WID = $WID]/wd:ID"/> 
     <xsl:text>"</xsl:text> 
     <!-- end new code --> 
     <xsl:value-of select="$linefeed"/> 
    </xsl:for-each> 
</xsl:for-each> 

Надеется, что это помогает!

+0

Спасибо за замечательные комментарии! Они так полезны, чтобы учиться. Будет ли переменная объявлена ​​так? BWatkins

+0

Это сработало! Спасибо, что ответили на мой вопрос и показали новичку, как использовать переменные. Я думал, что их нужно определить наверху. Еще раз спасибо, а также всем, кто внес вклад. – BWatkins

1

Вот решение, которое показывает несколько функций XSLT:

  • соответствия шаблона (в отличие от <xsl:for-each>)
  • ключей XSL
  • несколько режимов шаблона

(Я использовали URI фиктивного пространства имен для префикса wd)

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:wd="http://some.namespace/wd" 
> 
    <xsl:output method="text" /> 
    <xsl:key name="kPeople" match="wd:Beneficiaries_-_People" use="wd:WID" /> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="wd:Report_Data/wd:Report_Entry/wd:Beneficiaries_-_All" /> 
    </xsl:template> 

    <xsl:template match="wd:Beneficiaries_-_All"> 
    <xsl:apply-templates select="wd:EMPLID" mode="csv" /> 
    <xsl:apply-templates select="wd:Last" mode="csv" /> 
    <xsl:apply-templates select="wd:First" mode="csv" /> 
    <xsl:apply-templates select="key('kPeople', wd:WID)/wd:DOB" mode="csv" /> 
    <xsl:apply-templates select="key('kPeople', wd:WID)/wd:ID" mode="csv-nl" /> 
    </xsl:template> 

    <xsl:template match="*" mode="csv"> 
    <xsl:value-of select="concat('&quot;', ., '&quot;,')" /> 
    </xsl:template> 

    <xsl:template match="*" mode="csv-nl"> 
    <xsl:value-of select="concat('&quot;', ., '&quot;&#xA;')" /> 
    </xsl:template> 
</xsl:stylesheet> 

Для данных образца это приводит:

"00025","LastName","FirstName","Birth1","ID1" 
"00025","LastName","First2","Birth2","ID2" 

Gotchas:

  • Убедитесь, что двойные кавычки в значениях правильное обращения, поскольку в противном случае CSV будет нарушен. Либо убедитесь, что вы удалили их или сбежали от них должным образом. Получение этого права может быть сложным.
  • Это не работает, если некоторые элементы XML (например, <wd:DOB>) не существуют. Для равномерного ввода, где элементы всегда есть, но иногда пустые, все в порядке. Если элементы могут отсутствовать, скрипт нужно будет изменить.

В обоих случаях: Знайте ваши данные.


Соответствие шаблону - обоюдоострый меч. Это отлично подходит для управляемых вводами преобразований. Входной XML отображается через шаблоны в таблице стилей с минимальной сантехникой.

CSV, с другой стороны, является жестким выходным форматом, создавая его при помощи входного сигнала, требует, чтобы вход был таким же жестким. Поскольку XML позволяет пропускать элементы, может быть даже не элемент, который может быть превращен в поле вывода. В этом случае, именованные шаблоны и параметры могут помочь:

Вместо того

<xsl:apply-templates select="wd:EMPLID" mode="csv" /> 

мы могли бы

<xsl:call-template name="csv"> 
    <xsl:with-param name="val" value="wd:EMPLID" /> 
</xsl:call-template> 

и

<xsl:template name="csv"> 
    <xsl:param name="val" /> 
    <xsl:value-of select="concat('&quot;', $val, '&quot;,')" /> 
</xsl:call-template> 

Это убедиться, что даже если элемент отсутствует, пустое поле "", все равно будет напечатано.

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