Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 限制内联元素的长度_C#_Css_String_Xslt - Fatal编程技术网

C# 限制内联元素的长度

C# 限制内联元素的长度,c#,css,string,xslt,C#,Css,String,Xslt,如何限制可变长度文本元素的长度,该文本元素可以包含文本属性(,…)和链接。在打开和关闭时都需要保留标记,但如果在适当的位置(无法删除所有标记以简化问题),则可以删除整个标记(打开和关闭)。我可以使用c#、xslt和css。我不希望用javascript来实现这一点 例如: 关于用神经网络近似实现连续映射… 请记住,标记本身(及其属性)不应计入长度 此外,文本应该换行,因此使用宽度和溢出是不可能的 首席先生和迪米特里·诺瓦切夫都有很好的解决方案。我更喜欢将这种逻辑放在xslt中,因此我选择Dimi

如何限制可变长度文本元素的长度,该文本元素可以包含文本属性
(,…)
和链接。在打开和关闭时都需要保留标记,但如果在适当的位置(无法删除所有标记以简化问题),则可以删除整个标记(打开和关闭)。我可以使用c#、xslt和css。我不希望用javascript来实现这一点

例如:

关于用神经网络近似实现连续映射…

请记住,标记本身(及其属性)不应计入长度

此外,文本应该换行,因此使用宽度和溢出是不可能的


首席先生和迪米特里·诺瓦切夫都有很好的解决方案。我更喜欢将这种逻辑放在xslt中,因此我选择Dimitre Novatchev作为答案,尽管两者都应该如此。

这里有一个尝试性的解决方案:

    public static string LimitText(string input, int width)
    {
        const string pattern = @"(</?[a-zA-Z0-9 '=://.]+>)";  

        var rgx = new Regex(pattern, RegexOptions.Compiled);  

        // remove tags and chop text to set width
        var result = rgx.Replace(input, string.Empty).Substring(0, width);

        // split till word boundary (so that "shittake" doesn't end up as "shit")
        result = result.Substring(0, result.LastIndexOf(' '));

        var matches = rgx.Matches(input);

        // non LINQ version to keep things simple
        foreach (Match match in matches)
        {
            var groups = match.Groups;
            if (groups[0].Index > result.Length) break;
            result = result.Insert(groups[0].Index, groups[0].Value);
        }

        // check for unbalanced tags
        matches = rgx.Matches(result);

        if (matches.Count % 2 != 0)
        {
            // chop off unbalanced tag
            return result.Substring(0, matches[matches.Count-1].Groups[0].Index);
        }

        return result;
    }
publicstaticstringlimittext(字符串输入,int-width)
{
常量字符串模式=@“(result.Length)中断;
结果=结果。插入(组[0]。索引,组[0]。值);
}
//检查不平衡的标签
matches=rgx.matches(结果);
如果(匹配。计数%2!=0)
{
//切掉不平衡的标签
返回结果。子字符串(0,匹配[matches.Count-1]。组[0]。索引);
}
返回结果;
}
注意事项:

  • 正则表达式匹配文章中指定的所有标记。您可以根据实际场景对其进行扩展以包含更多字符。但是,解析 带有正则表达式的HTML总是很棘手的
  • 如果您的输入字符串不包含平衡标记(即,对于每个开始标记,都有一个结束标记),这可能无法按预期工作
  • 如果您希望在输入字符串中使用自动关闭标记(如

    )或打开
    输入
    标记,则需要进行飞行前消毒。同样,获取一组匹配项,运行
    LimitText
    ,然后在结果字符串上重新插入这些标记
  • 最终在浏览器上呈现的文本可能仍然不令人满意,因为字体大小或屏幕分辨率可能会产生不正确的结果。为此,您需要求助于基于JS的解决方案

  • 这应该让你开始,然后你可以在任何角落的情况下扩展它。

    网站设计不应该限制你可以在一个容器中放置什么信息。你可以设置元素的最大高度,并使用css允许悬停时的全高-你必须使用一些定位,可能还有一些负边距来防止其他错误元素跳来跳去

    或者,您可以使用文本溢出css属性,但这还没有完全实现(据我所知)-奇怪的是,它应该在ie6>中得到支持


    正则表达式解决方案很困难-您需要找到去掉标记的文本结尾的位置,剪切带标记的字符串的其余部分,并附加任何未关闭的标记-这是一个棘手的问题!

    此XSLT 1.0转换:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:key name="kTextById" match="text()" use="generate-id()"/>
    
     <xsl:param name="pMaxLength" select="60"/>
    
     <xsl:variable name="vTextToSplit">
      <xsl:apply-templates select="(//text())[1]" mode="calc"/>
     </xsl:variable>
    
    
    
     <xsl:variable name="vsplitNode" select=
    
         "key('kTextById', substring-before(substring-after($vTextToSplit,'|'), '|'))"/>
    
    
     <xsl:variable name="vsplitLength" select=
         "substring-before($vTextToSplit,'|')"/>
    
     <xsl:variable name="vsplitPos" select=
         "substring-after(substring-after($vTextToSplit,'|'),'|')"/>
    
     <xsl:template match="node()|@*">
    
      <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="/">
      <xsl:choose>
       <xsl:when test="not($vTextToSplit)">
        <xsl:copy-of select="."/>
       </xsl:when>
    
       <xsl:otherwise>
    
         <xsl:apply-templates select="/node()"/>
    
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
    
    
     <xsl:template match="text()" mode="calc">
      <xsl:param name="paccumLength" select="0"/>
    
    
      <xsl:variable name="vPos" select="count(preceding::text())+1"/>
    
    
      <xsl:variable name="vnewAccumLength" select=
                   "$paccumLength+string-length()"/>
    
      <xsl:choose>
       <xsl:when test="$vnewAccumLength >= $pMaxLength">
         <xsl:value-of select=
          "concat(string-length() - ($vnewAccumLength -$pMaxLength),
    
                  '|', generate-id(),
                  '|', $vPos
    
                  )"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:apply-templates mode="calc"
          select="(//text())[position() = $vPos+1]">
         <xsl:with-param name="paccumLength" select="$vnewAccumLength"/>
        </xsl:apply-templates>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
    
     <xsl:template match="text()">
      <xsl:variable name="vPos" select="count(preceding::text())+1"/>
    
      <xsl:choose>
       <xsl:when test="$vPos > $vsplitPos"/>
       <xsl:when test="$vPos = $vsplitPos">
        <xsl:value-of select="substring(.,1,$vsplitLength)"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="."/>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    </xsl:stylesheet>
    
    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes"/>
     <xsl:param name="pMaxLength" select="60"/>
    
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match=
     "text()[not(sum((.|preceding::text())/string-length(.))
                gt
                 $pMaxLength)
             ]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match=
     "text()[sum(preceding::text()/string-length(.))
                gt
                 $pMaxLength
             ]"/>
    
      <xsl:template match=
     "text()[sum((.|preceding::text())/string-length(.))
                ge
                 $pMaxLength
             and
              not(sum(preceding::text()/string-length(.))
                gt
                 $pMaxLength)
             ]">
    
      <xsl:variable name="vprevLength" select=
         "sum(preceding::text()/string-length(.))"/>
    
      <xsl:variable name="vremainingLength" select=
       "$pMaxLength - $vprevLength"/>
      <xsl:copy-of select="substring(.,1,$vremainingLength)"/>
     </xsl:template>
    
    </xsl:stylesheet>
    
    <t>On the <b>approximate realization</b> of continuous mappings by <i>neu</i><a href="http://...very long link"/></t>
    
    说明

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:key name="kTextById" match="text()" use="generate-id()"/>
    
     <xsl:param name="pMaxLength" select="60"/>
    
     <xsl:variable name="vTextToSplit">
      <xsl:apply-templates select="(//text())[1]" mode="calc"/>
     </xsl:variable>
    
    
    
     <xsl:variable name="vsplitNode" select=
    
         "key('kTextById', substring-before(substring-after($vTextToSplit,'|'), '|'))"/>
    
    
     <xsl:variable name="vsplitLength" select=
         "substring-before($vTextToSplit,'|')"/>
    
     <xsl:variable name="vsplitPos" select=
         "substring-after(substring-after($vTextToSplit,'|'),'|')"/>
    
     <xsl:template match="node()|@*">
    
      <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="/">
      <xsl:choose>
       <xsl:when test="not($vTextToSplit)">
        <xsl:copy-of select="."/>
       </xsl:when>
    
       <xsl:otherwise>
    
         <xsl:apply-templates select="/node()"/>
    
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
    
    
     <xsl:template match="text()" mode="calc">
      <xsl:param name="paccumLength" select="0"/>
    
    
      <xsl:variable name="vPos" select="count(preceding::text())+1"/>
    
    
      <xsl:variable name="vnewAccumLength" select=
                   "$paccumLength+string-length()"/>
    
      <xsl:choose>
       <xsl:when test="$vnewAccumLength >= $pMaxLength">
         <xsl:value-of select=
          "concat(string-length() - ($vnewAccumLength -$pMaxLength),
    
                  '|', generate-id(),
                  '|', $vPos
    
                  )"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:apply-templates mode="calc"
          select="(//text())[position() = $vPos+1]">
         <xsl:with-param name="paccumLength" select="$vnewAccumLength"/>
        </xsl:apply-templates>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
    
     <xsl:template match="text()">
      <xsl:variable name="vPos" select="count(preceding::text())+1"/>
    
      <xsl:choose>
       <xsl:when test="$vPos > $vsplitPos"/>
       <xsl:when test="$vPos = $vsplitPos">
        <xsl:value-of select="substring(.,1,$vsplitLength)"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="."/>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    </xsl:stylesheet>
    
    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes"/>
     <xsl:param name="pMaxLength" select="60"/>
    
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match=
     "text()[not(sum((.|preceding::text())/string-length(.))
                gt
                 $pMaxLength)
             ]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match=
     "text()[sum(preceding::text()/string-length(.))
                gt
                 $pMaxLength
             ]"/>
    
      <xsl:template match=
     "text()[sum((.|preceding::text())/string-length(.))
                ge
                 $pMaxLength
             and
              not(sum(preceding::text()/string-length(.))
                gt
                 $pMaxLength)
             ]">
    
      <xsl:variable name="vprevLength" select=
         "sum(preceding::text()/string-length(.))"/>
    
      <xsl:variable name="vremainingLength" select=
       "$pMaxLength - $vprevLength"/>
      <xsl:copy-of select="substring(.,1,$vremainingLength)"/>
     </xsl:template>
    
    </xsl:stylesheet>
    
    <t>On the <b>approximate realization</b> of continuous mappings by <i>neu</i><a href="http://...very long link"/></t>
    
  • 计算全局变量
    $vTextToSplit
    。它是一个字符串,包含三个以管道分隔的值:必须删除的“拆分节点”中的长度、
    生成-id()
    od“拆分节点”以及“拆分节点”在所有文本节点中的顺序位置,按文档顺序排列“拆分节点”是包含要生成的文本节点总字符串的最后一个字符的文本节点

  • 从“$vTextToSplit”中将“分割节点、其”
    generate-id()
    及其要修剪的长度提取为三个共同响应的全局变量

  • 当文本节点的总长度小于指定的所需长度时,匹配文档根(
    /
    )的模板将检查边缘大小写。如果是,则将完整的XML文档复制到输出。如果不是这样,则通过将模板应用于其子节点来继续处理

  • 标识规则“按原样”复制所有节点。

  • 与任何文本节点匹配的模板将覆盖标识模板。它通过以下三种方式之一处理匹配的文本节点:如果此文本节点的位置小于“拆分节点”,则会将其完全复制。如果匹配节点的位置大于“分割节点”,则不会复制其字符串值。最后,如果这是拆分节点本身,则会复制其字符串值的所有字符(尾部
    $vsplitLength
    字符除外)

  • II。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:key name="kTextById" match="text()" use="generate-id()"/>
    
     <xsl:param name="pMaxLength" select="60"/>
    
     <xsl:variable name="vTextToSplit">
      <xsl:apply-templates select="(//text())[1]" mode="calc"/>
     </xsl:variable>
    
    
    
     <xsl:variable name="vsplitNode" select=
    
         "key('kTextById', substring-before(substring-after($vTextToSplit,'|'), '|'))"/>
    
    
     <xsl:variable name="vsplitLength" select=
         "substring-before($vTextToSplit,'|')"/>
    
     <xsl:variable name="vsplitPos" select=
         "substring-after(substring-after($vTextToSplit,'|'),'|')"/>
    
     <xsl:template match="node()|@*">
    
      <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="/">
      <xsl:choose>
       <xsl:when test="not($vTextToSplit)">
        <xsl:copy-of select="."/>
       </xsl:when>
    
       <xsl:otherwise>
    
         <xsl:apply-templates select="/node()"/>
    
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
    
    
     <xsl:template match="text()" mode="calc">
      <xsl:param name="paccumLength" select="0"/>
    
    
      <xsl:variable name="vPos" select="count(preceding::text())+1"/>
    
    
      <xsl:variable name="vnewAccumLength" select=
                   "$paccumLength+string-length()"/>
    
      <xsl:choose>
       <xsl:when test="$vnewAccumLength >= $pMaxLength">
         <xsl:value-of select=
          "concat(string-length() - ($vnewAccumLength -$pMaxLength),
    
                  '|', generate-id(),
                  '|', $vPos
    
                  )"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:apply-templates mode="calc"
          select="(//text())[position() = $vPos+1]">
         <xsl:with-param name="paccumLength" select="$vnewAccumLength"/>
        </xsl:apply-templates>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
    
     <xsl:template match="text()">
      <xsl:variable name="vPos" select="count(preceding::text())+1"/>
    
      <xsl:choose>
       <xsl:when test="$vPos > $vsplitPos"/>
       <xsl:when test="$vPos = $vsplitPos">
        <xsl:value-of select="substring(.,1,$vsplitLength)"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="."/>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    </xsl:stylesheet>
    
    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes"/>
     <xsl:param name="pMaxLength" select="60"/>
    
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match=
     "text()[not(sum((.|preceding::text())/string-length(.))
                gt
                 $pMaxLength)
             ]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match=
     "text()[sum(preceding::text()/string-length(.))
                gt
                 $pMaxLength
             ]"/>
    
      <xsl:template match=
     "text()[sum((.|preceding::text())/string-length(.))
                ge
                 $pMaxLength
             and
              not(sum(preceding::text()/string-length(.))
                gt
                 $pMaxLength)
             ]">
    
      <xsl:variable name="vprevLength" select=
         "sum(preceding::text()/string-length(.))"/>
    
      <xsl:variable name="vremainingLength" select=
       "$pMaxLength - $vprevLength"/>
      <xsl:copy-of select="substring(.,1,$vremainingLength)"/>
     </xsl:template>
    
    </xsl:stylesheet>
    
    <t>On the <b>approximate realization</b> of continuous mappings by <i>neu</i><a href="http://...very long link"/></t>
    
    
    
    当应用于相同的源XML文档(如上所示)时,会产生相同的正确结果

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:key name="kTextById" match="text()" use="generate-id()"/>
    
     <xsl:param name="pMaxLength" select="60"/>
    
     <xsl:variable name="vTextToSplit">
      <xsl:apply-templates select="(//text())[1]" mode="calc"/>
     </xsl:variable>
    
    
    
     <xsl:variable name="vsplitNode" select=
    
         "key('kTextById', substring-before(substring-after($vTextToSplit,'|'), '|'))"/>
    
    
     <xsl:variable name="vsplitLength" select=
         "substring-before($vTextToSplit,'|')"/>
    
     <xsl:variable name="vsplitPos" select=
         "substring-after(substring-after($vTextToSplit,'|'),'|')"/>
    
     <xsl:template match="node()|@*">
    
      <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="/">
      <xsl:choose>
       <xsl:when test="not($vTextToSplit)">
        <xsl:copy-of select="."/>
       </xsl:when>
    
       <xsl:otherwise>
    
         <xsl:apply-templates select="/node()"/>
    
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
    
    
     <xsl:template match="text()" mode="calc">
      <xsl:param name="paccumLength" select="0"/>
    
    
      <xsl:variable name="vPos" select="count(preceding::text())+1"/>
    
    
      <xsl:variable name="vnewAccumLength" select=
                   "$paccumLength+string-length()"/>
    
      <xsl:choose>
       <xsl:when test="$vnewAccumLength >= $pMaxLength">
         <xsl:value-of select=
          "concat(string-length() - ($vnewAccumLength -$pMaxLength),
    
                  '|', generate-id(),
                  '|', $vPos
    
                  )"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:apply-templates mode="calc"
          select="(//text())[position() = $vPos+1]">
         <xsl:with-param name="paccumLength" select="$vnewAccumLength"/>
        </xsl:apply-templates>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    
    
     <xsl:template match="text()">
      <xsl:variable name="vPos" select="count(preceding::text())+1"/>
    
      <xsl:choose>
       <xsl:when test="$vPos > $vsplitPos"/>
       <xsl:when test="$vPos = $vsplitPos">
        <xsl:value-of select="substring(.,1,$vsplitLength)"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="."/>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    </xsl:stylesheet>
    
    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes"/>
     <xsl:param name="pMaxLength" select="60"/>
    
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match=
     "text()[not(sum((.|preceding::text())/string-length(.))
                gt
                 $pMaxLength)
             ]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match=
     "text()[sum(preceding::text()/string-length(.))
                gt
                 $pMaxLength
             ]"/>
    
      <xsl:template match=
     "text()[sum((.|preceding::text())/string-length(.))
                ge
                 $pMaxLength
             and
              not(sum(preceding::text()/string-length(.))
                gt
                 $pMaxLength)
             ]">
    
      <xsl:variable name="vprevLength" select=
         "sum(preceding::text()/string-length(.))"/>
    
      <xsl:variable name="vremainingLength" select=
       "$pMaxLength - $vprevLength"/>
      <xsl:copy-of select="substring(.,1,$vremainingLength)"/>
     </xsl:template>
    
    </xsl:stylesheet>
    
    <t>On the <b>approximate realization</b> of continuous mappings by <i>neu</i><a href="http://...very long link"/></t>
    

    关于连续映射的neu函数/模板的近似实现。当我有更多的空闲时间时,我会提供第三种解决方案。

    这是一个很好的问题,所以你希望的是只计算这个?”在通过神经网络近似实现连续映射的过程中,某些文本“是否正确?”将其设置为内联块并设置最大宽度?@Marc B-不能正确换行,它必须像内联文本一样工作,并且可能比该行上包含其他元素的行长。纯CSS无法做到这一点,因为它没有自己的计算能力。在CSS中唯一可以做的方法是在包含元素上设置一个固定的宽度并溢出:隐藏。其他任何事情都必须通过服务器端或客户端的javascript来完成。这是一个非常好的问题,+1。有关完整的XSLT1.0解决方案,请参见我的答案。生成的结果保留了所有格式,并保留了全部可显示文本