分组*几乎*独特的ID

时间:2011-04-26 21:52:46

标签: xslt

我正在努力解决几乎相同的分组ID。基本上我需要对PF.A1PF和PersIntr.Personnel.AlPersonnelActive部分的内容进行分组,然后去掉子字符串以获取我的id。我没有所有部分ID的列表。

请参阅下面的示例。

这是当前的XML:

<group>
<section id="unique_1_Connect_42_PF.AlPF">
    <msgph id="doc" xml:lang="en_US">It has been a external net failure. The pumps are
        blocked.</msgph>
    <msgph id="cstext" xml:lang="en_US">Mains error</msgph>
    <msgph id="localtext" xml:lang="en_US">Mains error</msgph>
</section>
<section id="unique_1_Connect_42_PersIntr.Personnel.AlPersonnelActive">
    <msgph id="doc" xml:lang="en_US">Personal alarm warning time has run out without reset.
        Personnel in danger !</msgph>
    <msgph id="cstext" xml:lang="en_US">Personal alarm</msgph>
    <msgph id="localtext" xml:lang="en_US">Pers. alarm</msgph>
</section>
<section id="unique_2_Connect_42_PF.AlPF">
    <msgph id="doc" xml:lang="es_ES">Ha habido un fallo de red externa. Las bombas están
        bloquedas.</msgph>
    <msgph id="cstext" xml:lang="es_ES">Fallo energía de entrada</msgph>
    <msgph id="localtext" xml:lang="es_ES">Fallo energía</msgph>
</section>
<section id="unique_2_Connect_42_PersIntr.Personnel.AlPersonnelActive">
    <msgph id="doc" xml:lang="es_ES">Tiempo de espera de la alarma de personal ha finalizado sin
        reseteo. ¡Personal en peligro!</msgph>
    <msgph id="cstext" xml:lang="es_ES">Alarma personal</msgph>
    <msgph id="localtext" xml:lang="es_ES">Alarma personal</msgph>
</section>

这是我需要输出的内容:

<Rsc Id="PF.AlPF">
    <Documentation en_US="It has been a external net failure. The pumps are blocked."
        es_ES="Ha habido un fallo de red externa. Las bombas están bloquedas."/>
    <CSText en_US="Mains error" es_ES="Fallo energía de entrada"/>
    <LocalText en_US="Mains error" es_ES="Fallo energía"/>
</Rsc>
<Rsc Id="PersIntr.Personnel.AlPersonnelActive">
    <Documentation
        en_US="Personal alarm warning time has run out without reset. Personnel in danger !"
        es_ES="Tiempo de espera de la alarma de personal ha finalizado sin reseteo. ¡Personal en peligro!"/>
    <CSText en_US="Personal alarm" es_ES="Alarma personal"/>
    <LocalText en_US="Pers. alarm" es_ES="Alarma personal"/>
</Rsc>

我非常感谢任何见解。提前感谢您的关注。

亲切的问候, 安


更新: 非常感谢@Dimitre,@ Michael。非常感谢您对这一挑战的帮助。我在2.0解决方案的这一部分中解决了元素问题:

<xsl:element name="{$vNewNames[starts-with(lower-case(.),current()/@id)]}">
    <xsl:for-each select="current-group()">
        <xsl:attribute name="{@xml:lang}" select="."/>
    </xsl:for-each>
</xsl:element> 

以下是最终奏效的内容:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
    <Resources>
        <Type key="Alarm">
            <xsl:for-each-group select="//section" group-by="substring-after(@id, '_42_')">
                <xsl:variable name="currentID" select="substring-after(@id, '_42_')"/>
                <xsl:element name="Rsc">
                    <xsl:attribute name="id" select="$currentID"/>                        
                    <xsl:for-each-group select="//section[$currentID]/msgph"
                        group-by="substring-after(@id, '_42_')">
                        <xsl:choose>
                            <xsl:when test="substring-after(@id, '_42_')='doc'">
                                <Documentation>
                                    <xsl:for-each select="current-group()">
                                        <xsl:if test="contains(parent::*/@id,$currentID)">
                                            <xsl:attribute name="{@xml:lang}" select="."/>
                                        </xsl:if>
                                    </xsl:for-each>
                                </Documentation>
                            </xsl:when>
                            <xsl:when test="substring-after(@id, '_42_')='cstext'">
                                <CSText>
                                    <xsl:for-each select="current-group()">
                                        <xsl:if test="contains(parent::*/@id,$currentID)">
                                            <xsl:attribute name="{@xml:lang}" select="."/>
                                        </xsl:if>
                                    </xsl:for-each>
                                </CSText>
                            </xsl:when>
                            <xsl:when test="substring-after(@id, '_42_')='localtext'">
                                <LocalText>
                                    <xsl:for-each select="current-group()">
                                        <xsl:if test="contains(parent::*/@id,$currentID)">
                                            <xsl:attribute name="{@xml:lang}" select="."/>
                                        </xsl:if>
                                    </xsl:for-each>
                                </LocalText>
                            </xsl:when>
                        </xsl:choose>
                    </xsl:for-each-group>
                </xsl:element>
            </xsl:for-each-group>
        </Type>
    </Resources>
</xsl:template>

再次感谢! 安

3 个答案:

答案 0 :(得分:1)

此转化

<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:key name="ksectById" match="section"
  use="substring-after(@id, '42_')"/>

 <xsl:template match=
 "section[generate-id()
         =
          generate-id(key('ksectById',
                      substring-after(@id, '42_')
                         )[1]
                      )
         ]
 ">
  <xsl:variable name="vId" select=
  "substring-after(@id, '42_')"/>

  <xsl:variable name="vGroup" select=
   "key('ksectById',$vId)"/>

  <Rsc Id="{$vId}">
   <Documentation>
     <xsl:apply-templates select=
      "$vGroup/msgph[@id='doc']/@xml:lang"/>
   </Documentation>
   <CSText>
     <xsl:apply-templates select=
      "$vGroup/msgph[@id='cstext']/@xml:lang"/>
   </CSText>
   <LocalText>
     <xsl:apply-templates select=
      "$vGroup/msgph[@id='localtext']/@xml:lang"/>
   </LocalText>
  </Rsc>
 </xsl:template>

 <xsl:template match="@xml:lang">
  <xsl:attribute name="{.}">
   <xsl:value-of select=".."/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="*/*" priority="-1"/>
</xsl:stylesheet>

应用于提供的XML文档

<group>
    <section id="unique_1_Connect_42_PF.AlPF">
        <msgph id="doc" xml:lang="en_US">It has been a external net failure. The pumps are blocked.</msgph>
        <msgph id="cstext" xml:lang="en_US">Mains error</msgph>
        <msgph id="localtext" xml:lang="en_US">Mains error</msgph>
    </section>
    <section id="unique_1_Connect_42_PersIntr.Personnel.AlPersonnelActive">
        <msgph id="doc" xml:lang="en_US">Personal alarm warning time has run out without reset. Personnel in danger !</msgph>
        <msgph id="cstext" xml:lang="en_US">Personal alarm</msgph>
        <msgph id="localtext" xml:lang="en_US">Pers. alarm</msgph>
    </section>
    <section id="unique_2_Connect_42_PF.AlPF">
        <msgph id="doc" xml:lang="es_ES">Ha habido un fallo de red externa. Las bombas están bloquedas.</msgph>
        <msgph id="cstext" xml:lang="es_ES">Fallo energía de entrada</msgph>
        <msgph id="localtext" xml:lang="es_ES">Fallo energía</msgph>
    </section>
    <section id="unique_2_Connect_42_PersIntr.Personnel.AlPersonnelActive">
        <msgph id="doc" xml:lang="es_ES">Tiempo de espera de la alarma de personal ha finalizado sin reseteo. ¡Personal en peligro!</msgph>
        <msgph id="cstext" xml:lang="es_ES">Alarma personal</msgph>
        <msgph id="localtext" xml:lang="es_ES">Alarma personal</msgph>
    </section>
</group>

产生完全正确的结果

<Rsc Id="PF.AlPF">
   <Documentation en_US="It has been a external net failure. The pumps are blocked." es_ES="Ha habido un fallo de red externa. Las bombas están bloquedas."/>
   <CSText en_US="Mains error" es_ES="Fallo energía de entrada"/>
   <LocalText en_US="Mains error" es_ES="Fallo energía"/>
</Rsc>
<Rsc Id="PersIntr.Personnel.AlPersonnelActive">
   <Documentation en_US="Personal alarm warning time has run out without reset. Personnel in danger !" es_ES="Tiempo de espera de la alarma de personal ha finalizado sin reseteo. ¡Personal en peligro!"/>
   <CSText en_US="Personal alarm" es_ES="Alarma personal"/>
   <LocalText en_US="Pers. alarm" es_ES="Alarma personal"/>
</Rsc>

解释Muenchian grouping,其键定义为id属性的子字符串。

<强> II。 XSLT 2.0解决方案:

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

 <xsl:variable name="vNewNames" select=
 "'Documentation', 'CSText', 'LocalText'"/>

 <xsl:template match="/*">
     <xsl:for-each-group select="section"
          group-by="substring-after(@id, '_42_')">

        <xsl:variable name="vId" select=
            "substring-after(@id, '42_')"/>

        <Rsc Id="{$vId}">
         <xsl:for-each-group select="current-group()/*"
              group-by="@id">
           <xsl:element name=
             "{$vNewNames[starts-with(lower-case(.),current()/@id)]}">
            <xsl:for-each select="current-group()">
             <xsl:attribute name="{@xml:lang}" select="."/>
            </xsl:for-each>
           </xsl:element>
         </xsl:for-each-group>
        </Rsc>
     </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

此代码使用了一些非常强大且最自然的XSLT 2.0功能,例如<xsl:for-eac-group>current-group(),序列,select <xsl:attribute>属性}}。结果几乎是代码的两倍,更易读和可维护。

答案 1 :(得分:0)

我不太了解XSLT,但似乎你应该能够使用XSLT substring function来删除每个部分[id]的前22个字符并返回重要部分。

答案 2 :(得分:0)

定义“差不多”。只有这样,你才能找到合理的解决方案。您很可能会使用基本的xslt函数自行解决它。