XSLT 2 或 3 - 使用 for-each-group : group-starting-with 向平面 XML 文件添加结构

问题描述 投票:0回答:1

我收到了一个 Verity .otl 文件,并被要求“解码”,以便可以重新制定所有规则。

我很自然地想到将文本文件转换为 XML 并进行处理。我的第一遍创建 XML 并添加有用的属性。这是我第一遍的输出示例。

  <?xml version="1.0" encoding="UTF-8"?>
<root>  
     <line pos="1" Lv="1" val="# topic_OST_Agri_export |Or|"/>
     <line pos="2" Lv="2" val="## topic_OST_Export_contracts |Or|"/>
     <line pos="3" Lv="3" val="### |Phrase|"/>
     <line pos="4" Lv="4" val="#### ~export~"/>
     <line pos="5" Lv="4" val="#### |Wildcard| /wordtext = ~contract#~"/>
     <line pos="6" Lv="3" val="### ~contract for the export~"/>
     <line pos="7" Lv="3" val="### |Phrase|"/>
     <line pos="8" Lv="4" val="#### ~contract~"/>
     <line pos="9" Lv="4" val="#### ~for~"/>
     <line pos="10" Lv="4" val="#### |Wildcard| /wordtext = ~export#~"/>
     <line pos="11" Lv="2" val="## topic_OST_Export_figures |Or|"/>
     <line pos="12" Lv="3" val="### |Phrase|"/>
     <line pos="13" Lv="4" val="#### ~export~"/>
     <line pos="14" Lv="4" val="#### |Wildcard| /wordtext = ~figure#~"/>
     <line pos="15" Lv="3" val="### ~export statistics~"/>
     <line pos="16" Lv="3" val="### |Phrase|"/>
     <line pos="17" Lv="4" val="#### ~Agriculturle~"/>
     <line pos="18" Lv="4" val="#### |Wildcard| /wordtext = ~export#~"/>
     <line pos="19" Lv="4" val="#### |Wildcard| /wordtext = ~increas#~"/>
     <line pos="20" Lv="3" val="### |Phrase|"/>
     <line pos="21" Lv="4" val="#### ~defence~"/>
     <line pos="22" Lv="4" val="#### |Wildcard| /wordtext = ~export#~"/>
     <line pos="23" Lv="4" val="#### |Wildcard| /wordtext = ~reach#~"/>
     <line pos="24" Lv="3" val="### |Near/6|"/>
     <line pos="25" Lv="4" val="#### |Phrase|"/>
     <line pos="26" Lv="5" val="##### ~Agri~"/>
     <line pos="27" Lv="5" val="##### |Wildcard| /wordtext = ~export#~"/>
     <line pos="28" Lv="4" val="#### |Any|"/>
     <line pos="29" Lv="5" val="##### ~statistics~"/>
     <line pos="30" Lv="5" val="##### ~trends~"/>
     <line pos="31" Lv="5" val="##### ~figures~"/>
     <line pos="32" Lv="5" val="##### |Wildcard| /wordtext = ~annual#~"/>
     <line pos="33" Lv="5" val="##### ~per cent~"/>
     <line pos="34" Lv="5" val="##### ~million~"/>
     <line pos="35" Lv="5" val="##### ~billion~"/>
     <line pos="36" Lv="2" val="## ~Agri export~"/>
     <line pos="37" Lv="2" val="## ~Agri exports~"/>
   <line pos="38" Lv="2" val="## ~exporting Agri~"/>
</root>

这只是 70k 行文件的一个片段。

我想将其转换为 xml 结构,根据 @Lv 对行进行分组

上面的一个例子是( @Type 和 @calledFrom 是我在尝试理解数据并实现目标时添加的,但没有成功)

 <line pos="1" Lv="1" val="# topic_OST_Agri_export |Or|">
  
     <line pos="2" Lv="2" val="## topic_OST_Export_contracts |Or|" Type="Topic"
           calledFrom="1">
        <line pos="3" Lv="3" val="### |Phrase|" Type="phrase">
           <line pos="4" Lv="4" val="#### ~export~" Type="Word"/>
           <line pos="5" Lv="4" val="#### |Wildcard| /wordtext = ~contract#~" Type="Wildcard"/>
           <line pos="6" Lv="3" val="### ~contract for the export~" Type="Word"/>
           <line pos="7" Lv="3" val="### |Phrase|" Type="phrase">
              <line pos="8" Lv="4" val="#### ~contract~" Type="Word"/>
              <line pos="9" Lv="4" val="#### ~for~" Type="Word"/>
              <line pos="10" Lv="4" val="#### |Wildcard| /wordtext = ~export#~" Type="Wildcard"/>
           </line>
        </line>
     </line>

我已经在哪些方面失败了?

递归:xsl:选择不同的@Type。这看起来很有希望,但由于在不应该的情况下吞噬了后续的行而失败了。

我觉得以组为起点是构建数据以供进一步处理和理解的答案,但一天后我只是没有“理解”以组为起点。

我在 Stack Overflow 上读到的关于类似问题的最后一篇文章已结束

“诀窍在于真正理解小组起始应该是 模式不是条件。” 块引用 块引用

来源:grouping-xml-elements-using-xslts-for-each-group-and-group-starting-with-attrib

当然,非常欢迎任何有关如何测试以下兄弟姐妹属性并测试小组中是否需要他们的指导。

grouping xslt-2.0 xslt-3.0
1个回答
1
投票

关于所需输出的问题...为什么 Lv="3" 行是其他 Lv="3" 行的子行?他们不是兄妹吗?

如果他们应该是兄弟姐妹,您可以执行递归模板调用来获取下一个级别。

示例...

XSLT 3.0

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" expand-text="yes" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template match="/*">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:call-template name="nest_levels">
                <xsl:with-param name="ctx" select="line"/>
                <xsl:with-param name="current_level" select="1"/>
            </xsl:call-template>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template name="nest_levels">
        <xsl:param name="ctx" required="yes" as="element()*"/>
        <xsl:param name="current_level" required="yes" as="xs:double"/>
        <xsl:for-each select="$ctx[@Lv=$current_level]">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
                <xsl:if test="following-sibling::line[1]/@Lv > $current_level">
                    <xsl:call-template name="nest_levels">
                        <xsl:with-param name="ctx" select="following-sibling::line[preceding-sibling::line[@Lv=$current_level][1] is current()]"/>
                        <xsl:with-param name="current_level" select="following-sibling::line[1]/@Lv"/>
                    </xsl:call-template>
                </xsl:if>
            </xsl:copy>
        </xsl:for-each>
    </xsl:template>
    
</xsl:stylesheet>

输出

<root>
   <line pos="1" Lv="1" val="# topic_OST_Agri_export |Or|">
      <line pos="2" Lv="2" val="## topic_OST_Export_contracts |Or|">
         <line pos="3" Lv="3" val="### |Phrase|">
            <line pos="4" Lv="4" val="#### ~export~"/>
            <line pos="5" Lv="4" val="#### |Wildcard| /wordtext = ~contract#~"/>
         </line>
         <line pos="6" Lv="3" val="### ~contract for the export~"/>
         <line pos="7" Lv="3" val="### |Phrase|">
            <line pos="8" Lv="4" val="#### ~contract~"/>
            <line pos="9" Lv="4" val="#### ~for~"/>
            <line pos="10" Lv="4" val="#### |Wildcard| /wordtext = ~export#~"/>
         </line>
      </line>
      <line pos="11" Lv="2" val="## topic_OST_Export_figures |Or|">
         <line pos="12" Lv="3" val="### |Phrase|">
            <line pos="13" Lv="4" val="#### ~export~"/>
            <line pos="14" Lv="4" val="#### |Wildcard| /wordtext = ~figure#~"/>
         </line>
         <line pos="15" Lv="3" val="### ~export statistics~"/>
         <line pos="16" Lv="3" val="### |Phrase|">
            <line pos="17" Lv="4" val="#### ~Agriculturle~"/>
            <line pos="18" Lv="4" val="#### |Wildcard| /wordtext = ~export#~"/>
            <line pos="19" Lv="4" val="#### |Wildcard| /wordtext = ~increas#~"/>
         </line>
         <line pos="20" Lv="3" val="### |Phrase|">
            <line pos="21" Lv="4" val="#### ~defence~"/>
            <line pos="22" Lv="4" val="#### |Wildcard| /wordtext = ~export#~"/>
            <line pos="23" Lv="4" val="#### |Wildcard| /wordtext = ~reach#~"/>
         </line>
         <line pos="24" Lv="3" val="### |Near/6|">
            <line pos="25" Lv="4" val="#### |Phrase|">
               <line pos="26" Lv="5" val="##### ~Agri~"/>
               <line pos="27" Lv="5" val="##### |Wildcard| /wordtext = ~export#~"/>
            </line>
            <line pos="28" Lv="4" val="#### |Any|">
               <line pos="29" Lv="5" val="##### ~statistics~"/>
               <line pos="30" Lv="5" val="##### ~trends~"/>
               <line pos="31" Lv="5" val="##### ~figures~"/>
               <line pos="32" Lv="5" val="##### |Wildcard| /wordtext = ~annual#~"/>
               <line pos="33" Lv="5" val="##### ~per cent~"/>
               <line pos="34" Lv="5" val="##### ~million~"/>
               <line pos="35" Lv="5" val="##### ~billion~"/>
            </line>
         </line>
      </line>
      <line pos="36" Lv="2" val="## ~Agri export~"/>
      <line pos="37" Lv="2" val="## ~Agri exports~"/>
      <line pos="38" Lv="2" val="## ~exporting Agri~"/>
   </line>
</root>
© www.soinside.com 2019 - 2024. All rights reserved.