необходимо поместить повторяющиеся узлы XML в отдельные узлы с помощью xsl / xslt - PullRequest
3 голосов
/ 16 апреля 2019

У меня есть этот xml:

<products>
 <product>
 <name>ad</name>
 <category>something</category>
 <path>something</path>
    <size>S</size>
    <color-code>87-3</color-code>
    <size-code>24294</size-code>
    <size-qty>10</size-qty>
    <size-codeproducer>5902228002604</size-codeproducer>
    <size>M</size>
    <color-code>87-4</color-code>
    <size-code>24295</size-code>
    <size-qty>64</size-qty>
    <size-codeproducer>5902228002611</size-codeproducer>
    <size>L</size>
    <color-code>87-5</color-code>
    <size-code>24296</size-code>
    <size-qty>46</size-qty>
    <size-codeproducer>5902228002628</size-codeproducer>
    <size>XXL</size>
    <color-code>87-7</color-code>
    <size-code>24298</size-code>
    <size-qty>0</size-qty>
    <size-codeproducer>5902228002635</size-codeproducer>
    <imgs>
      <img>pictures/large/7/8/87_2.jpg</img>
      <img>pictures/large/7/8/87_1.jpg</img>
      <img>pictures/large/7/8/87_4.jpg</img>
      <img>pictures/large/7/8/87_5.jpg</img>
      <img>pictures/large/7/8/87_3.jpg</img>
      <img>pictures/large/7/8/87_6.jpg</img>
    </imgs>google.com</url>
    <price>7.98</price>
    <brand>NIKE</brand>
    <color>black</color>
    <gender>Man</gender>
  </product>
  <product>
  ...
  ...
  ...
  </product>
</products>

что мне нужно:

<products>
<product>
<name>ad</name>
<category>something</category>
...
<variation>
   <size>S</size>
   <color-code>87-3</color-code>
   <size-code>24294</size-code>
   <size-qty>10</size-qty>
   <size-codeproducer>5902228002604</size-codeproducer>
</variation>
<variation>
   <size>M</size>
   <color-code>87-4</color-code>
   <size-code>24295</size-code>
   <size-qty>64</size-qty>
   <size-codeproducer>5902228002611</size-codeproducer>
</variation>
<variation>
   <size>L</size>
   <color-code>87-5</color-code>
   <size-code>24296</size-code>
   <size-qty>46</size-qty>
   <size-codeproducer>5902228002628</size-codeproducer>
</variation>
<variation>
   <size>XXL</size>
   <color-code>87-7</color-code>
   <size-code>24298</size-code>
   <size-qty>0</size-qty>
   <size-codeproducer>5902228002635</size-codeproducer>
</variation>
</product>
<product>
...
</product>
</products>

У меня есть этот xsl:

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

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

     <xsl:template match="/products/product">

        <xsl:copy>
            <xsl:copy-of select="description|id|name|category|path"/>
            <xsl:for-each select="/products/product/size">
                <variation>
                    <xsl:variable name="occur" select="position()"/>
                    <xsl:copy-of select="."/>
                    <xsl:copy-of select="/products/product/color-code[$occur]"/>
                    <xsl:copy-of select="/products/product/size-code[$occur]"/>
                    <xsl:copy-of select="/products/product/size-qty[$occur]"/>
                    <xsl:copy-of select="/products/product/size-codeproducer[$occur]"/>
                </variation>
            </xsl:for-each>
            <xsl:copy-of select="imgs|url|price|brand|color|gender"/>
        </xsl:copy>

     </xsl:template>
</xsl:stylesheet>

И результаты XMLфайл, который копирует size-codeproducer, color-code, size-code и size-qty в каждом узле продукта.любая помощь будет принята.

Я пробовал различные варианты копирования xsl - для каждого цикла и другие вещи, но большинство из них ничего не печатало после разбора, печатало тот же документ или были другиепроблемы.Я предполагаю, что проблема в путях (xpaths?), Которые я использую.

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Во-первых, у вас есть проблема с вашим xsl:for-each ...

<xsl:for-each select="/products/product/size">

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

<xsl:for-each select="size">

И аналогично, для различных операторов xsl:copy-of вместо того, чтобы делать это ...

<xsl:copy-of select="/products/product/color-code[$occur]"/>

Вы должны сделать это (где .. получает родительский элемент текущего size элемента)

<xsl:copy-of select="../color-code[$occur]"/>

Попробуйте использовать этот шаблон вместо

 <xsl:template match="/products/product">
    <xsl:copy>
        <xsl:copy-of select="description|id|name|category|path"/>
        <xsl:for-each select="size">
            <variation>
                <xsl:variable name="occur" select="position()"/>
                <xsl:copy-of select="."/>
                <xsl:copy-of select="../color-code[$occur]"/>
                <xsl:copy-of select="../size-code[$occur]"/>
                <xsl:copy-of select="../size-qty[$occur]"/>
                <xsl:copy-of select="../size-codeproducer[$occur]"/>
            </variation>
        </xsl:for-each>
        <xsl:copy-of select="imgs|url|price|brand|color|gender"/>
    </xsl:copy>
 </xsl:template>

(Обратите внимание, что вы также можетевыполните <xsl:copy-of select="following-sibling::color-code[1]"/> здесь и аналогично для других операторов).

1 голос
/ 17 апреля 2019

Просто чтобы показать другой подход к группированию смежных областей или начинанию с чего-то в XSLT 1.0, эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="shallow-copy">
     <xsl:copy>
      <xsl:apply-templates select="node()[1]|@*"/>
     </xsl:copy>
     <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>

    <xsl:template match="size">
     <variation>
      <xsl:call-template name="group-starting-with"/>
     </variation>
     <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>

    <xsl:template match="color-code|size-code|size-qty|size-codeproducer">
     <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>

    <xsl:template match="node()" mode="group-starting-with"
      name="group-starting-with">
      <xsl:copy>
       <xsl:apply-templates select="node()[1]|@*"/>
      </xsl:copy>
      <xsl:apply-templates select="following-sibling::node()[1]" 
       mode="group-starting-with"/>
    </xsl:template>

    <xsl:template match="size|imgs" mode="group-starting-with"/>
</xsl:stylesheet>

выход

<products> 
  <product> 
    <name>ad</name>  
    <category>something</category>  
    <path>something</path>  
    <variation> 
      <size>S</size>  
      <color-code>87-3</color-code>  
      <size-code>24294</size-code>  
      <size-qty>10</size-qty>  
      <size-codeproducer>5902228002604</size-codeproducer> 
    </variation>  
    <variation> 
      <size>M</size>  
      <color-code>87-4</color-code>  
      <size-code>24295</size-code>  
      <size-qty>64</size-qty>  
      <size-codeproducer>5902228002611</size-codeproducer> 
    </variation>  
    <variation> 
      <size>L</size>  
      <color-code>87-5</color-code>  
      <size-code>24296</size-code>  
      <size-qty>46</size-qty>  
      <size-codeproducer>5902228002628</size-codeproducer> 
    </variation>  
    <variation> 
      <size>XXL</size>  
      <color-code>87-7</color-code>  
      <size-code>24298</size-code>  
      <size-qty>0</size-qty>  
      <size-codeproducer>5902228002635</size-codeproducer> 
    </variation>  
    <imgs> 
      <img>pictures/large/7/8/87_2.jpg</img>  
      <img>pictures/large/7/8/87_1.jpg</img>  
      <img>pictures/large/7/8/87_4.jpg</img>  
      <img>pictures/large/7/8/87_5.jpg</img>  
      <img>pictures/large/7/8/87_3.jpg</img>  
      <img>pictures/large/7/8/87_6.jpg</img> 
    </imgs>  
    <url>google.com</url>  
    <price>7.98</price>  
    <brand>NIKE</brand>  
    <color>black</color>  
    <gender>Man</gender> 
  </product>  
  <product>... ... ...</product> 
</products>

Обратите внимание : это обход следующего топора. Это означает, что каждое правило отвечает за применение шаблонов к первому дочернему элементу и первому после родного брата. Для группировки вам нужно правило с критерием соответствия для запуска, пустые правила для остановки при несоответствии критерию и обход правил, когда критерий совпадает, но вы не группируете.

...