Xslt 分组*几乎*唯一ID

Xslt 分组*几乎*唯一ID,xslt,Xslt,我正在努力将几乎相同的ID分组。基本上,我需要对PF.A1PF和PersIntr.personal.alpersonelative部分的内容进行分组,并在获取id之前剥离子字符串。我没有所有部分id的列表 请参见下面的示例 以下是当前的XML: <group> <section id="unique_1_Connect_42_PF.AlPF"> <msgph id="doc" xml:lang="en_US">It has been a externa

我正在努力将几乎相同的ID分组。基本上,我需要对PF.A1PF和PersIntr.personal.alpersonelative部分的内容进行分组,并在获取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>

我真的很感激你的洞察力。提前感谢您的关注

亲切问候,, 安妮


更新: 非常感谢,迪米特里,迈克尔。我真的很感谢你在这次挑战中的帮助。在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>

再次感谢!
Anne

我对XSLT了解不多,但似乎您应该能够使用XSLT去掉每个节[id]的前22个字符并返回重要部分。

我对XSLT了解不多,但似乎您应该能够使用XSLT去掉每个节[id]的前22个字符并返回重要部分。

定义“几乎”。只有这样你才能想出一个合理的解决办法。然后,您很可能会使用基本的xslt函数自己解决这个问题

定义“几乎”。只有这样你才能想出一个合理的解决办法。然后,您很可能会使用基本的xslt函数自己解决这个问题

此转换:

<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>
<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>
<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: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>
<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>
<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功能,例如
当前组()
,序列,
选择
属性。结果是代码缩短了近两倍,可读性和可维护性大大提高。

前缀模式是否像
unique\u35; uconnect\u42
一样被修复?好问题,+1。有关使用Muenchian方法进行分组的完整解决方案,请参阅我的答案。前缀“pattern”是否像
unique\u35;\u Connect\u 42\uuuu
一样固定?好问题,+1。请参阅我的答案,了解使用Muenchian方法进行分组的完整解决方案。哎哟,好的。忘了提我认为很明显的…我是一个新手,正在挣扎。哎哟,好吧。忘了提我认为很明显的…我是一个新手,正在挣扎。谢谢你,耶利米。我没有想过使用枚举来过滤掉我不需要的字符。你好,阿桑克斯,耶利米。我没有想过使用枚举来过滤掉我不需要的字符。您好,我有点惊讶,当海报上没有说他们必须使用XSLT1.0时,您竟然为分组问题提供了XSLT1.0解决方案。2.0中的解决方案会更容易理解,特别是对于一个不熟悉这门语言的人来说。@Michael Kay:我理解你的感受——两年前我也有同样的感受。我们必须接受人们不知道也不使用XSLT2.0的现实。这会影响新来者接触和学习XSLT2.0的速度,因为很少有人可以指导他们学习XSLT2.0,而且人们普遍认为XSLT2.0“更复杂”。我同意这是不幸的,但XSLT 1.0是99%(参见XSLT、XPath、XSLT-2.0、XPath-2.0的问题数量)这些人想要并请求帮助的东西:(.有什么改进的建议吗?@Michael Kay:添加了XSLT 2.0解决方案。我有点惊讶,当海报上没有说他们必须使用XSLT 1.0时,你竟然为分组问题提供了XSLT 1.0解决方案。2.0中的解决方案会更容易理解,特别是对于不熟悉该语言的人。@Micha艾尔凯:我了解你的费用