2017-02-23 38 views
0
From the XML below, I am trying to achieve this final output 
XML 
<root> 
<Primary_Key>12345</Primary_Key> 
<First_Name>ABC</First_Name> 
<Last_Name>DEF<Last_Name> 
<Bank_Account> 
<Bank_Name>ABC Bank</Bank_Name> 
<Bank_Account_No>123456</Bank_Account_No> 
</Bank_Account> 
<Bank_Account> 
<Bank_Name>DEF Bank</Bank_Name> 
<Bank_Account_No>789012</Bank_Account_No> 
</Bank_Account> 
<Organization>Pharma</Organization> 
<Organization>Inventory</Organization> 
</root> 

Вывод, который я хочу видеть это:Несколько строк в выводе XSL

12345, ABC, DEF, ABC банка, 123456, Pharma
+12345 ,,, DEF Bank, 789012, инвентарь

Итак, в основном каждое поле, имеющее несколько значений, должно быть заполнено в следующей строке другими полями, имеющими несколько значений. Если бы была третья организация под названием "Supply", то выход должен был

12345, ABC, DEF, ABC банка, 123456, Pharma
+12345 ,,, DEF Bank, 789012, инвентарь
12345 ,, ,,, Поставка

не в состоянии получить мою голову вокруг того, как мы будем петлю вокруг для выборки данных

+1

«* в основном каждое поле, которое имеет несколько значений должно быть заполнено в следующем ряду с другими полями, которые имеют несколько значений. *» Вы должны выяснить, есть ли одно поле - например «Организация» - это всегда будет иметь максимальное количество значений. –

ответ

1

Создание шаблона вокруг Primary_Key. Используйте это для запуска цикла генерации строк на Bank_Account. Если количество Organization элементов превышает количество элементов Bank_Account, запустите дополнительные циклы строк. Если необходимо, чтобы избежать дублирования (например, потому что вы используете шаблон идентификации), вызовите пустой шаблон для каждого элемента не Primary_Key.

<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <output method="text"/> 
    <template match="child::Primary_Key"> 
     <variable name="organizations.outnumber.bank.accounts" select="count(following-sibling::Bank_Account) &lt; count(following-sibling::Organization)"/> 
     <for-each select="following-sibling::Bank_Account"> 
      <variable name="row.number" select="position()"/> 
      <value-of select="concat(preceding-sibling::Primary_Key/child::text(), ',')"/> 
      <choose> 
       <when test="$row.number = 1"> 
        <value-of select="concat(preceding-sibling::First_Name/child::text(), ',', preceding-sibling::Last_Name/child::text(), ',')"/> 
       </when> 
       <otherwise>,,</otherwise> 
      </choose> 
      <value-of select="concat(child::Bank_Name/child::text(), ',', child::Bank_Account_No/child::text(), ',')"/> 
      <if test="count(following-sibling::Organization[position() = $row.number]) = 1"> 
       <value-of select="following-sibling::Organization[position() = $row.number]/child::text()"/> 
      </if> 
      <if test="not(self::Bank_Account[position() = last()]) or $organizations.outnumber.bank.accounts"> 
       <text>&#xa;</text> 
      </if> 
     </for-each> 
     <if test="$organizations.outnumber.bank.accounts"> 
      <variable name="row.start.number" select="count(following-sibling::Bank_Account) + 1"/> 
      <for-each select="following-sibling::Organization[position() >= $row.start.number]"> 
       <variable name="row.number" select="position()"/> 
       <value-of select="concat(preceding-sibling::Primary_Key/child::text(), ',,,,,')"/> 
       <value-of select="self::Organization[position() = $row.number]/child::text()"/> 
       <if test="not(self::Organization[position() = last()])"> 
        <text>&#xa;</text> 
       </if> 
      </for-each> 
     </if> 
    </template> 
    <template match="child::root"> 
     <apply-templates select="child::Primary_Key"/> 
    </template> 
</transform> 

При использовании шаблона идентичности, использовать <template match="child::Primary_Key/following-sibling::*"/>, чтобы свести на нет остальных элементов.

2

Это легкий шаг

<xsl:template match="/"> 
    <xsl:for-each select="//Organization"> 
     <xsl:variable name="pos" select="position()"/> 
     <xsl:text>&#xa;</xsl:text> 
     <xsl:value-of select="concat(parent::root/Primary_Key, ',' , parent::root/First_Name[$pos], ',' , parent::root/Last_Name[$pos], ',' , parent::root/Bank_Account[$pos]/Bank_Name, ',' , parent::root/Bank_Account[$pos]/Bank_Account_No, ',', current())"/> 
    </xsl:for-each> 
</xsl:template> 
+1

Мне нравится это решение лучше, чем у меня, хотя оно предполагает, что элементы 'Organization' будут всегда превосходить элементы' Bank_Account', которые могут быть или не быть истинными для кода OP. Он также выводит ненужный новый символ линии в начале, который может быть исправлен с помощью ''. –

+0

Чтобы разместить то, что указывает @PatrickDark, я беру счет каждого поля в начале и используя наивысший счетчик в моем цикле for. – user502808

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