在SVG文档中遍历子节点的问题

 
在SVG文档中遍历子节点的问题
修订:
2007-03-12 删除了BATIK不计算空白节点的描述,因为在实际编程中发现BATIK1.6也将空白节点计算为子节点。不知道 www.carto.net中对BATIK节点计算的描述是否基于早期的BATIK版本。
相信很多使用Adobe SVG Viewer(ASV)进行SVG编程的都遇到过这个问题,在使用节点遍历时,返回的节点数总是有些奇怪,例如在SVG文档中如果写入:
 
<g id="choices">
 <!--this is a test-->
 <text x="20" y="100" font-size="30">by their</text>
 <text x="20" y="100" font-size="30">by their</text>
</g>
      
然后使用如下代码取该组下的子节点数量:
 
var elem = svgDocument.getElementById("choices");
var nodes = elem.childNodes;
alert(nodes.length);
 
我们期望返回的个数为3,包括一个注释和两个文本节点,但ASV实际返回为7。网上有些文档解释如下:
 
childNodes 中子节点列表的序号是从 1 开始,并且以 2 递增的。因此访问的方式为
for(var i = 1;i < ((nodes.length-1));i = i+2)
{
            alert(printNode(nodes.item(i)));
}
 
事实上这是不对的,在ASV中,节点下的空白也作为一个节点计算,因此上面的节点还要加上四个空白节点,因此是7个。如果我们在SVG中以不换行的方式写上述节点,
 
<g id="choices"> <!--this is a test--> <text x="20" y="100" font-size="30">by their</text> <text x="20" y="100" font-size="30">by their</text></g>
 
这时返回的节点数是3。在这种情况下,上面的代码就有问题了。特别是在我们动态生成SVG图形时,这个问题比较比较明显了。例如在原始的SVG文档中有:
 
<g id="choices">
</g>
 
       然后在脚本中,使用createElementNS在组中动态创建几个矩形图形节点:
 
var group = svgDocument.getElementById("choices ");
       for(var i=0; i < 3; i++)
       {
                     var elem = svgDocument.createElementNS(svgns, "rect" );
                     group.appendChild(elem);
       }
       此时组中的子节点数量为4(三个矩形节点和一个空白节点),对矩形子节点的遍历就应当是:
 
var elem = svgDocument.getElementById("choices");
       var nodes = elem.childNodes;
                      
       for(var i = 1; i < nodes.length ;i ++)
       {
            alert(nodes.item(i).nodeName);
       }
 
       但如果原始的文档中写为
<g id="choices"></g>
 
       在动态创建子节点后,组中子节点数量为3,对矩形子节点的遍历的遍历为:
 
var elem = svgDocument.getElementById("choices");
       var nodes = elem.childNodes;
                      
       for(var i = 0; i < nodes.length ;i ++)
       {
            alert(nodes.item(i).nodeName);
       }
 
       可见遍历循环的条件取决于原始文档中节点的写法,这是我们不希望的。因此,正确的方法是, 总是遍历所有子节点,然后根据节点的名称进行过滤。
 
              var elem = svgDocument.getElementById("choices ");
        var nodes = elem.getChildNodes;
      
            for(i = 0;i < nodes.length ;i ++)
              {
                         if(nodes.item(i).nodeName == "#text")
                                continue;
                           
                            // Do something
              }
 
       或者
 
              var elem = svgDocument.getElementById("choices ");
        var nodes = elem.getChildNodes;
      
            for(i = 0;i < nodes.length ;i ++)
              {
                         if(nodes.item(i).nodeName == "rect")
{
                                   // Do something
}
              }
 
       特别是在编写可以不同的SVG浏览器中移植的代码时,使用上述方式尤为重要,因为不同的浏览器对空白处理子是不一样的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值