XSLT: копировать вложенный элемент несколько раз - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь скопировать один из вложенных элементов несколько раз.Я искал и наткнулся на XSLT: копировать объект xml несколько раз, увеличивая атрибут и значение .Это близко, но не тот ответ, который я ищу.Это то, что я пытаюсь сделать

Вход XML:

<Company xmlns="http://test.com" >
    <Group document="dump" >
        <dump>asdfasd</dump>
        <dump2>asdfasdf</dump2>
        <Person>
            <record>1</record>
            <dump2>asdfasdf</dump2>
            <properties>
                <name>John</name>
                <number>1</number>
            </properties>
        </Person>
    </Group>
</Company>

И выводить что-то вроде:

<Company xmlns="http://test.com">
   <Group document="dump">
      <dump>asdfasd</dump>
      <dump2>asdfasdf</dump2>
      <Person>
         <record>1</record>
         <dump2>asdfasdf</dump2>
         <properties>
            <name>John</name>
            <number>1</number>
         </properties>
      </Person>
      ...
      <Person>
         <record>n</record>
         <dump2>asdfasdf</dump2>
         <properties>
            <name>John</name>
            <number>n</number>
         </properties>
      </Person>
   </Group>
</Company>

С моим xslt:

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

     <xsl:param name="pTimes" select="2"/>

     <xsl:template match="node()|@*">
      <xsl:param name="pPosition" select="1"/>
      <xsl:copy>
       <xsl:apply-templates select="node()|@*">
         <xsl:with-param name="pPosition" select="$pPosition"/>
       </xsl:apply-templates>
      </xsl:copy>
     </xsl:template>

     <xsl:template match="t:Person">
         <xsl:copy>
             <xsl:copy-of select="@*"/>
             <xsl:call-template name="applyNTimes">
                 <xsl:with-param name="pTimes" select="$pTimes"/>
                 <xsl:with-param name="pPosition" select="1"/>
             </xsl:call-template>
          </xsl:copy>
     </xsl:template>

     <xsl:template name="applyNTimes">
         <xsl:param name="pTimes" select="0"/>
         <xsl:param name="pPosition" select="1"/>

         <xsl:if test="$pTimes > 0">
             <xsl:choose>
             <xsl:when test="$pTimes = 1">
                 <xsl:apply-templates select="*">
                 <xsl:with-param name="pPosition" select="$pPosition"/>
                 </xsl:apply-templates>
             </xsl:when>
             <xsl:otherwise>
                 <xsl:variable name="vHalf" select="floor($pTimes div 2)"/>

                 <xsl:call-template name="applyNTimes">
                 <xsl:with-param name="pTimes" select="$vHalf"/>
                 <xsl:with-param name="pPosition" select="$pPosition"/>
                 </xsl:call-template>

                 <xsl:call-template name="applyNTimes">
                 <xsl:with-param name="pTimes" select="$pTimes - $vHalf"/>
                 <xsl:with-param name="pPosition" select="$pPosition + $vHalf"/>
                 </xsl:call-template>
             </xsl:otherwise>
             </xsl:choose>
         </xsl:if>
     </xsl:template>

     <xsl:template match="t:record">
         <xsl:param name="pPosition" select="1"/>

         <xsl:copy>
              <xsl:value-of select="$pPosition"/>
          </xsl:copy>
     </xsl:template>

     <xsl:template match="t:number">
          <xsl:param name="pPosition" select="1"/>
            <xsl:copy>
              <xsl:value-of select="$pPosition"/>
            </xsl:copy>
     </xsl:template>
</xsl:stylesheet>

Это то, что у меня есть

<Company xmlns="http://test.com">
   <Group document="dump">
      <dump>asdfasd</dump>
      <dump2>asdfasdf</dump2>
      <Person position="1">
         <record>1</record>
         <dump2>asdfasdf</dump2>
         <properties>
            <name>John</name>
            <number>1</number>
         </properties>
         <record>2</record>
         <dump2>asdfasdf</dump2>
         <properties>
            <name>John</name>
            <number>2</number>
         </properties>
      </Person>
   </Group>
</Company>

Как мне предотвратить элемент Person отисчезает при копировании?

1 Ответ

0 голосов
/ 19 октября 2018

Решение в этом случае состоит в том, чтобы переместить xsl:copy для Персона из шаблона, соответствующего t:Person, в шаблон applyNTimes (в случае, когда pTimes равен 1).

Попробуйте этот XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:t="http://test.com" version="1.0">
   <xsl:output omit-xml-declaration="yes" indent="yes"></xsl:output>
   <xsl:strip-space elements="*"></xsl:strip-space>
   <xsl:param name="pTimes" select="2"></xsl:param>

   <xsl:template match="node()|@*">
      <xsl:param name="pPosition" select="1"></xsl:param>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*">
            <xsl:with-param name="pPosition" select="$pPosition"></xsl:with-param>
         </xsl:apply-templates>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="t:Person">
      <xsl:call-template name="applyNTimes">
         <xsl:with-param name="pTimes" select="$pTimes"></xsl:with-param>
         <xsl:with-param name="pPosition" select="1"></xsl:with-param>
      </xsl:call-template>
   </xsl:template>

   <xsl:template name="applyNTimes">
      <xsl:param name="pTimes" select="0"></xsl:param>
      <xsl:param name="pPosition" select="1"></xsl:param>
      <xsl:if test="$pTimes &gt; 0">
         <xsl:choose>
            <xsl:when test="$pTimes = 1">
               <xsl:copy>
                  <xsl:apply-templates select="*">
                     <xsl:with-param name="pPosition" select="$pPosition"></xsl:with-param>
                  </xsl:apply-templates>
               </xsl:copy>
            </xsl:when>
            <xsl:otherwise>
               <xsl:variable name="vHalf" select="floor($pTimes div 2)"></xsl:variable>
               <xsl:call-template name="applyNTimes">
                  <xsl:with-param name="pTimes" select="$vHalf"></xsl:with-param>
                  <xsl:with-param name="pPosition" select="$pPosition"></xsl:with-param>
               </xsl:call-template>
               <xsl:call-template name="applyNTimes">
                  <xsl:with-param name="pTimes" select="$pTimes - $vHalf"></xsl:with-param>
                  <xsl:with-param name="pPosition" select="$pPosition + $vHalf"></xsl:with-param>
               </xsl:call-template>
            </xsl:otherwise>
         </xsl:choose>
      </xsl:if>
   </xsl:template>

   <xsl:template match="t:record|t:number">
      <xsl:param name="pPosition" select="1"></xsl:param>
      <xsl:copy>
         <xsl:value-of select="$pPosition"></xsl:value-of>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

Обратите внимание, что если вы сможете использовать XSLT 2.0, то все станет намного проще благодаря поддержке конструкции «от 1 до n» (и существованию «туннелирования», чтобы избежатьявно передавать параметры в каждый шаблон).

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:t="http://test.com" 
                version="2.0">

   <xsl:output omit-xml-declaration="yes" indent="yes"></xsl:output>
   <xsl:strip-space elements="*"></xsl:strip-space>

   <xsl:param name="pTimes" select="2"></xsl:param>

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

   <xsl:template match="t:Person">
      <xsl:variable name="person" select="." />
      <xsl:for-each select="1 to $pTimes">
        <xsl:apply-templates select="$person" mode="repeat">
           <xsl:with-param name="pPosition" select="position()" tunnel="yes" />
        </xsl:apply-templates>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="t:Person" mode="repeat">
     <xsl:copy>
       <xsl:apply-templates />
     </xsl:copy>
   </xsl:template>

   <xsl:template match="t:record|t:number">
      <xsl:param name="pPosition" select="1" tunnel="yes"></xsl:param>
      <xsl:copy>
         <xsl:value-of select="$pPosition"></xsl:value-of>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...