【问题标题】:xslt 1.0 - Standardize/Sanitize Spaces based on a delimiter and then tokenize results (Vanilla XSLT Only)xslt 1.0 - 基于分隔符标准化/清理空间,然后标记化结果(仅限 Vanilla XSLT)
【发布时间】:2021-01-03 18:57:05
【问题描述】:

我有数据,我需要根据" - " 标记化,注意连字符的每一边都有一个空格,但是,在解析了十万行之后,我注意到一些数据周围缺少空格连字符,这打破了我的逻辑。

我尝试使用 concat 和 substring 来查找断开的连字符并添加空格,但无论我尝试什么,我都无法解决所有情况。我认为最好的目标是找到所有连字符,并确保每边正好有 1 个空格。不过,老实说,我完全愿意接受建议。

已编辑,我需要解决此示例。我正在考虑将安全词列表添加到标记化中可能是最简单的。但是,我不知道该怎么做。

<part>
    <partDescription>Belden Gloves- Hi-Viz - Orange -Small</partDescription>
</part>

https://xsltfiddle.liberty-development.net/nb9PtDF/1

<root>
    <!--99% of the 200k records are this first below record -->
    <part>
        <partDescription>Awesome Shirts - Chocolate/Black - Medium</partDescription>
    </part>
       
    <!-- However, there are a few hundred that didn't space the delimiter correctly 
         this causes my token template to not function as expected-->
    <part>
        <partDescription>Bantam Gloves - Chocolate/Black -Medium</partDescription>
    </part>
    <part>
        <partDescription>Belden Gloves- Black - Large</partDescription>
    </part>
    <part>
        <partDescription>Belden Gloves - Heatshield - Red- Small</partDescription>
    </part>
    <part>
        <partDescription>Belden Hats -Orange -Small</partDescription>
    </part>
    <part>
        <partDescription>XSLT Jacket- Black -Small</partDescription>
    </part>
</root>

当前 XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
                xmlns:php="http://php.net/xsl"
                exclude-result-prefixes="php"
                version="1.0">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:key name="part-by-product" match="part" use="productId" />
    <xsl:strip-space elements="*"/>

    <xsl:template match="part">        
        <item>                

            <!--Struggling here :( -->
            <xsl:call-template name="tokenizeDescription">
                <!--<xsl:with-param name="text" select= "partDescription"/>-->
                <xsl:with-param name="text" select= 
                    "concat( substring-before(partDescription, '- '), ' - ', 
                            substring-after(partDescription, '- ') )"/>
            
            </xsl:call-template>
            
        </item>
    </xsl:template>
    
    <!-- Parse Description as Keys  -->
    <xsl:template name="tokenizeDescription">
        <xsl:param name="text"/>
        <xsl:param name="delimiter" select="' - '"/>
        <xsl:param name="partType"/>
        <xsl:param name="keys">
            <xsl:choose>
                <xsl:when test="contains(partDescription, 'Heatshield')">short_name,benefit,color,size,</xsl:when>
                <xsl:otherwise>short_name,color,size,</xsl:otherwise>
            </xsl:choose>
        </xsl:param>
        
        <xsl:element name="{substring-before($keys, ',')}">
            <xsl:value-of select="substring-before(concat($text, $delimiter), $delimiter)" />
        </xsl:element>
        <xsl:if test="contains($text, $delimiter)">
            <xsl:call-template name="tokenizeDescription">
                <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
                <xsl:with-param name="keys" select="substring-after($keys, ',')"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

预期结果

<?xml version="1.0" encoding="UTF-8"?>
<item>
   <short_name>Awesome Shirts</short_name>
   <color>Chocolate/Black</color>
   <size>Medium</size>
</item>
<item>
   <short_name>Bantam Gloves</short_name>
   <color>Chocolate/Black</color>
   <size>Medium</size>
</item>
<item>
   <short_name>Belden Gloves</short_name>
   <color>Black</color>
   <size>Large</size>
</item>
<item>
   <short_name>Belden Gloves</short_name>
   <benefit>Heatshield</benefit>
   <color>Red</color>
   <size>Small</size>
</item>
<item>
   <short_name>Belden Hats</short_name>
   <color>Orange</color>
   <size>Small</size>
</item>
<item>
   <short_name>XSLT Jacket</short_name>
   <color>Black</color>
   <size>Small</size>
</item>

实际结果

<?xml version="1.0" encoding="UTF-8"?>
<item>
   <short_name>Awesome Shirts </short_name>
   <color>Chocolate/Black</color>
   <size>Medium</size>
</item>
<item>
   <short_name>Bantam Gloves </short_name>
   <color>Chocolate/Black -Medium</color>
</item>
<item>
   <short_name>Belden Gloves</short_name>
   <color>Black</color>
   <size>Large</size>
</item>
<item>
   <short_name>Belden Gloves </short_name>
   <benefit>Heatshield</benefit>
   <color>Red- Small</color>
</item>
<item>
   <short_name/>
   <color/>
</item>
<item>
   <short_name>XSLT Jacket</short_name>
   <color>Black -Small</color>
</item>

【问题讨论】:

  • 您是否遇到过连字符不是分隔符的情况?
  • 连字符应始终作为分隔符。但是,最好有一个关于是否应该运行清理过程的标志,以防万一。
  • 如果连字符始终是分隔符,则将其(单独)用作分隔符并使用normalize-space() 去掉多余的空格。我不明白“消毒”部分。
  • 我的意思是“清理”,就像清理分隔符周围的空间一样。我不知道如何让 normalize-space 工作,因为我一直在删除单词之间的有效空格。我将如何使用它来不删除有效空格,而只删除分隔符周围的空格?然后我可以调整标记化模板以使用“-”而不是“-”
  • xsltfiddle.liberty-development.net/nb9PtDF/2 做你想做的事吗?或者单词之间可以有多个空格,您需要保留它们吗?

标签: xml xslt xslt-1.0


【解决方案1】:

这可能会有所帮助。如果您有任何问题,请告诉我。

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

<xsl:template match="partDescription">
  <xsl:variable name="nodes">
    <xsl:call-template name="getNodesFromDelimitedList">
      <xsl:with-param name="inStrList" select="."/>
      <xsl:with-param name="delimiter" select="'-'"/>
    </xsl:call-template>
  </xsl:variable>  

  <!-- *** NOTE *** Make sure you use your prefix to create the node set, not msxml.  -->
  <xsl:variable name="nodeList" select="msxml:node-set($nodes)"/>

  <xsl:choose>
    <xsl:when test="contains(., 'Heatshield')">
      <xsl:element name="item">
        <xsl:element name="short_name">
          <xsl:value-of select="$nodeList/element[1]"/>
        </xsl:element>

        <xsl:element name="benefit">
          <xsl:value-of select="$nodeList/element[2]"/>
        </xsl:element>
 
        <xsl:element name="color">
          <xsl:value-of select="$nodeList/element[3]"/>
        </xsl:element>

        <xsl:element name="size">
          <xsl:value-of select="$nodeList/element[4]"/>
        </xsl:element>
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:element name="item">
        <xsl:element name="short_name">
          <xsl:value-of select="$nodeList/element[1]"/>
        </xsl:element>
  
        <xsl:element name="color">
          <xsl:value-of select="$nodeList/element[2]"/>
        </xsl:element>

        <xsl:element name="size">
          <xsl:value-of select="$nodeList/element[3]"/>
        </xsl:element>
      </xsl:element>
    </xsl:otherwise>          
  </xsl:choose>

</xsl:template>
  
<xsl:template name="getNodesFromDelimitedList">
  <!-- Delimited string with one or more delimiters.  -->
  <xsl:param name="inStrList"/>
  <!-- The delimiter. -->
  <xsl:param name="delimiter" select="'|'"/>

  <xsl:choose>
    <xsl:when test="contains($inStrList,$delimiter)">
      <!-- Get the first element from the list.  -->
      <xsl:variable name="element" select="substring-before($inStrList,$delimiter)"/>

      <!-- Put the element in the list.  -->
      <xsl:element name="element">
        <xsl:value-of select="normalize-space($element)"/>
      </xsl:element>

      <!-- Call template to process the next element. -->
      <xsl:call-template name="getNodesFromDelimitedList">
        <xsl:with-param name="inStrList" select="substring-after($inStrList,$delimiter)"/>
        <xsl:with-param name="delimiter" select="$delimiter"/>
      </xsl:call-template>

    </xsl:when>
    <xsl:otherwise>
      <!-- Put the element in the list.  -->
      <xsl:element name="element">
        <xsl:value-of select="normalize-space($inStrList)"/>
      </xsl:element>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

【讨论】:

  • 你能帮我在我的小提琴中设置这个吗?不幸的是,节点匹配的使用超出了我的想象。
  • 此代码是满足您要求的一种方式。您唯一需要解决的是代码中提到的节点集函数的前缀。只需备份您的代码,删除您的密钥和模板,将其粘贴,修复节点集前缀,您应该会很好。祝你好运!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2013-03-17
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多