使用变量控制在xml中显示的级别数(xslt)

时间:2016-05-16 17:55:50

标签: xml xslt xpath

我需要以下帮助。 我正在使用xslt准备xml文件。

我有一个xml文件

<?xml version="1.0" encoding="utf-8"?>
<root>
  <productgroup1>
    <groupname>groupname 1</groupname>
    <groupdescription>groupdescription 1</groupdescription>
    <groupimage>groupimage 1</groupimage>
    <productgroup2>
      <groupname>groupname 2</groupname>
      <groupdescription>groupdescription 2</groupdescription>
      <groupimage>groupimage 2</groupimage>
      <productgroup3>
        <groupname>groupname 3</groupname>
        <groupdescription>groupdescription 3</groupdescription>
        <groupimage>groupimage 3</groupimage>
        <products>
          <product>
            <Name>DDD</Name>
            <Number>FFF</Number>
            <Price>GGG</itemPrice>
            <Color>HHH</Color>
            <ExGroup>JJJ</ExGroup>
          </product>
          <product>
            <Name>XXX</Name>
            <Number>CCC</Number>
            <Price>VVV</Price>
            <Color>BBB</Color>
            <ExProductgroup>NNN</ExProductgroup>
          </product>
        </products>
      </productgroup3>
    </productgroup2>
  </productgroup1>
</root> 

我需要用xslt对它进行转换,它应该处理动态级别和条件。

例如: 如果我有4级xml并且我只显示3个级别(基于变量),则第4级的所有内容将根据以下变量进入第3级: GroupLevels = 3 IncludeGroupsFurhterDown =是

如果IncludeGroupsFurhterDown = No,则应删除第4级。

XSLT文件(没有变量)

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

 <xsl:variable name="GroupLevels">3</xsl:variable> 
 <xsl:variable name="IncludeGroupsFurhterDown">Yes</xsl:variable> 

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

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

输出XML:

 <root>
  <productgroup1>
    <groupname>groupname 1</groupname>
    <groupdescription>groupdescription 1</groupdescription>
    <groupimage>groupimage 1</groupimage>
    <productgroup2>
      <groupname>groupname 2</groupname>
      <groupdescription>groupdescription 2</groupdescription>
      <groupimage>groupimage 2</groupimage>
      <productgroup3>
        <groupname>groupname 3</groupname>
        <groupdescription>groupdescription 3</groupdescription>
        <groupimage>groupimage 3</groupimage>
        <product>
          <itemName>Hårdvaxolja natur</itemName>
          <itemNumber>64563</itemNumber>
          <itemPrice>0</itemPrice>
          <itemColor>Opigmenterad</itemColor>
          <ExtraProductgroup>Trappnos</ExtraProductgroup>
        </product>
        <product>
          <itemName>Test</itemName>
          <itemNumber>44353</itemNumber>
          <itemPrice>43</itemPrice>
          <itemColor>Rerfdf</itemColor>
          <ExtraProductgroup>Asasfdr</ExtraProductgroup>
        </product>
      </productgroup3>
    </productgroup2>
  </productgroup1>
</root>

1 个答案:

答案 0 :(得分:0)

这是一个解决方案:

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

 <xsl:param name="pGroupLevels" select="3"/>
 <xsl:param name="pIncludeGroupsFurhterDown" select="'Yes'"/>

  <xsl:template match=
  "*[starts-with(name(), 'productgroup') 
    and 
     substring-after(name(), 'productgroup') 
    = 
     number(substring-after(name(), 'productgroup'))]">
    <xsl:variable name="vNestLevel" 
                  select="number(substring-after(name(), 'productgroup'))"/>

    <xsl:if test="not($vNestLevel > $pGroupLevels)">
        <xsl:copy>
          <xsl:copy-of select=
          "*[not(self::products) and not(starts-with(name(), 'productgroup') 
           and substring-after(name(), 'productgroup') 
              = 
               number(substring-after(name(), 'productgroup')))]"/>

           <xsl:apply-templates select=
           "*[not($vNestLevel > $pGroupLevels -1)
          and
            starts-with(name(), 'productgroup') 
          and 
           substring-after(name(), 'productgroup') 
          = 
           number(substring-after(name(), 'productgroup'))]
           "/>

          <xsl:copy-of select=
            "(*[starts-with(name(), 'productgroup') 
          and 
           substring-after(name(), 'productgroup') 
          = 
           number(substring-after(name(), 'productgroup'))]/* 
        | .//products/product)[$vNestLevel = $pGroupLevels 
                               and 
                                 $pIncludeGroupsFurhterDown = 'Yes']"/>
        </xsl:copy>
    </xsl:if>
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

在提供的XML文档上应用此转换时

<root>
    <productgroup1>
        <groupname>groupname 1</groupname>
        <groupdescription>groupdescription 1</groupdescription>
        <groupimage>groupimage 1</groupimage>
        <productgroup2>
            <groupname>groupname 2</groupname>
            <groupdescription>groupdescription 2</groupdescription>
            <groupimage>groupimage 2</groupimage>
            <productgroup3>
                <groupname>groupname 3</groupname>
                <groupdescription>groupdescription 3</groupdescription>
                <groupimage>groupimage 3</groupimage>
                <products>
                    <product>
                        <Name>DDD</Name>
                        <Number>FFF</Number>
                        <Price>GGG</Price>
                        <Color>HHH</Color>
                        <ExGroup>JJJ</ExGroup>
                    </product>
                    <product>
                        <Name>XXX</Name>
                        <Number>CCC</Number>
                        <Price>VVV</Price>
                        <Color>BBB</Color>
                        <ExProductgroup>NNN</ExProductgroup>
                    </product>
                </products>
            </productgroup3>
        </productgroup2>
    </productgroup1>
</root>

产生了想要的正确结果

<productgroup1>
   <groupname>groupname 1</groupname>
   <groupdescription>groupdescription 1</groupdescription>
   <groupimage>groupimage 1</groupimage>
   <productgroup2>
      <groupname>groupname 2</groupname>
      <groupdescription>groupdescription 2</groupdescription>
      <groupimage>groupimage 2</groupimage>
      <productgroup3>
         <groupname>groupname 3</groupname>
         <groupdescription>groupdescription 3</groupdescription>
         <groupimage>groupimage 3</groupimage>
         <product>
            <Name>DDD</Name>
            <Number>FFF</Number>
            <Price>GGG</Price>
            <Color>HHH</Color>
            <ExGroup>JJJ</ExGroup>
         </product>
         <product>
            <Name>XXX</Name>
            <Number>CCC</Number>
            <Price>VVV</Price>
            <Color>BBB</Color>
            <ExProductgroup>NNN</ExProductgroup>
         </product>
      </productgroup3>
   </productgroup2>
</productgroup1>

当我们编辑转化并指定:

 <xsl:param name="pIncludeGroupsFurhterDown" select="'No'"/>

再次产生了想要的,正确的结果:

<productgroup1>
   <groupname>groupname 1</groupname>
   <groupdescription>groupdescription 1</groupdescription>
   <groupimage>groupimage 1</groupimage>
   <productgroup2>
      <groupname>groupname 2</groupname>
      <groupdescription>groupdescription 2</groupdescription>
      <groupimage>groupimage 2</groupimage>
      <productgroup3>
         <groupname>groupname 3</groupname>
         <groupdescription>groupdescription 3</groupdescription>
         <groupimage>groupimage 3</groupimage>
      </productgroup3>
   </productgroup2>
</productgroup1>