如何用XmlDocument或LINQ XDocument替换SVG文本元素的InnerText为超链接
处理SVG文本元素添加链接的问题
需求描述
处理SVG文件(本质为XML)时,需要将指定<text>元素的文本内容替换为包含原文本的带href属性的<a>元素,避免原文本与链接文本重复显示。
原元素与期望效果
原<text>元素
<text xmlns="http://www.w3.org/2000/svg" xml:space="preserve" fill="#ff0000" stroke-width="0" x="239.61" y="74.89" font-size="3.37" opacity="1.00" font-family="Arial Narrow">3070119100</text>
期望结果(两种场景)
场景1:保留<text>元素,内部嵌套<a>
<text xmlns="http://www.w3.org/2000/svg" xml:space="preserve" fill="#ff0000" stroke-width="0" x="239.61" y="74.89" font-size="3.37" opacity="1.00" font-family="Arial Narrow"> <a xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.google.it">3070119100</a> </text>
场景2:直接将<text>替换为<a>
<a xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.google.it">3070119100</a>
现有问题
使用XmlDocument添加<a>子元素后,原<text>的文本内容未清除,导致原文本与链接文本重复显示。
解决方案
方案1:XmlDocument实现(保留<text>,清除原文本)
在添加<a>子元素前,通过设置InnerText = string.Empty清除原文本内容:
XmlDocument doc = new XmlDocument(); doc.Load(_SVG); XmlNodeList elementListText = doc.GetElementsByTagName("text"); for (int i = 0; i < elementListText.Count; i++) { XmlElement a = doc.CreateElement("a"); a.SetAttribute("xmlns", "http://www.w3.org/2000/svg"); a.SetAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); a.SetAttribute("xlink:href", "http://www.google.it"); a.InnerText = elementListText[i].InnerText; // 清除原文本,避免重复 elementListText[i].InnerText = string.Empty; elementListText[i].AppendChild(a); } doc.Save(_SVG_TEXT);
方案2:LINQ to XDocument实现(保留<text>,清除原文本)
利用LINQ操作XML,先移除<text>的所有子节点(原文本),再添加<a>元素:
XDocument doc = XDocument.Load(_SVG); XNamespace svgNs = "http://www.w3.org/2000/svg"; XNamespace xlinkNs = "http://www.w3.org/1999/xlink"; foreach (var textElement in doc.Descendants(svgNs + "text")) { string originalText = textElement.Value; // 移除原文本节点 textElement.RemoveNodes(); var aElement = new XElement(svgNs + "a", new XAttribute(XNamespace.Xmlns + "xlink", xlinkNs.NamespaceName), new XAttribute(xlinkNs + "href", "http://www.google.it"), originalText); textElement.Add(aElement); } doc.Save(_SVG_TEXT);
方案3:XmlDocument实现(替换<text>为<a>)
如果需要直接替换整个<text>元素为<a>,可使用节点替换操作:
XmlDocument doc = new XmlDocument(); doc.Load(_SVG); XmlNodeList elementListText = doc.GetElementsByTagName("text"); // 倒序遍历防止索引错乱 for (int i = elementListText.Count - 1; i >= 0; i--) { XmlNode textNode = elementListText[i]; XmlElement a = doc.CreateElement("a"); a.SetAttribute("xmlns", "http://www.w3.org/2000/svg"); a.SetAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); a.SetAttribute("xlink:href", "http://www.google.it"); a.InnerText = textNode.InnerText; // 替换原<text>节点 textNode.ParentNode.ReplaceChild(a, textNode); } doc.Save(_SVG_TEXT);
方案4:LINQ to XDocument实现(替换<text>为<a>)
XDocument doc = XDocument.Load(_SVG); XNamespace svgNs = "http://www.w3.org/2000/svg"; XNamespace xlinkNs = "http://www.w3.org/1999/xlink"; // 先转为List避免遍历中修改集合 var textElements = doc.Descendants(svgNs + "text").ToList(); foreach (var textElement in textElements) { var aElement = new XElement(svgNs + "a", new XAttribute(XNamespace.Xmlns + "xlink", xlinkNs.NamespaceName), new XAttribute(xlinkNs + "href", "http://www.google.it"), textElement.Value); // 替换原<text>元素 textElement.ReplaceWith(aElement); } doc.Save(_SVG_TEXT);
内容的提问来源于stack exchange,提问作者chriswaddle
相关产品推荐
相关产品推荐

