对*几乎*唯一的 ID 进行分组

发布于 2024-11-03 15:32:30 字数 5912 浏览 0 评论 0原文

我正在努力将几乎相同的 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>

再次感谢! 安妮

I'm struggling with grouping ids that are almost the same. Basically I need to group the content of the PF.A1PF and PersIntr.Personnel.AlPersonnelActive sections and strip the substring before to get my id. I do not have a listing of all the section ids.

Please see below for examples.

Here's the current 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>

Here's what I need to output:

<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>

I really appreciate any insight. Thanks in advance for your attention.

Kind regards,
Anne


Update:
Thanks so much, @Dimitre, @Michael. I really appreciate your help with this challenge. I had a little trouble with the element resolving in this portion of the 2.0 solution:

<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> 

Here's what finally worked:

<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>

Thanks again!
Anne

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞旧 2024-11-10 15:32:30

此转换

<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>

说明:< a href="http://www.jeniitennison.com/xslt/grouping/muenchian.html" rel="nofollow">Muenchian 分组,其键定义为以下子字符串id 属性。

二. 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 功能,例如 current-group()、序列、select 属性。结果是代码几乎缩短了一倍,并且更具可读性和可维护性。

This transformation:

<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>

when applied on the provided XML document:

<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>

produces exactly the wanted, correct result:

<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>

Explanation: Muenchian grouping with key that is defined as a substring of the id attribute.

II. XSLT 2.0 solution:

<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>

This code uses some very powerful and most natural XSLT 2.0 features, such as <xsl:for-eac-group>, current-group(), sequences, the select attribute of <xsl:attribute>. The result is almost twice shorter code that is much more readable and maintainable.

贱人配狗天长地久 2024-11-10 15:32:30

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

I don't know a considerable amount about XSLT, but it seems like you should be able to use the XSLT substring function to strip out the first 22 characters of each section[id] and return the significant portion.

送舟行 2024-11-10 15:32:30

定义“几乎”。只有这样你才能想出一个合理的解决方案。您很可能会使用基本的 xslt 函数自行解决该问题。

Define "almost". Only then you'll be able to come up with a reasonable solution. Most likely you will then solve it yourself with basic xslt functions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文