如何根据某些属性选择 xml 元素并将其完整写回到另一个文件中

发布于 2024-12-27 16:11:35 字数 1903 浏览 0 评论 0原文

我正在使用 XmlTextReader 读取 svg/xml,并且我想将其中的一些元素写回到新的 svg/xml 文件中,

<svg>
    <rect x="135.7" y="537.4" fill="none" stroke="#000000" stroke-width="0.2894" width="36.6" height="42.2"/>
    <rect x="99" y="537.4" fill="#A0C9EC" stroke="#000000" stroke-width="0.2894" width="36.7" height="42.2"/>
</svg>

我想要用“none”填充的 rect 元素,所以我开始读取和写入,

 var reader = new XmlTextReader(file.InputStream);
 var writer = new XmlTextWriter(svgPath + fileNameWithoutExtension + "-less" + extension, null);
 writer.WriteStartDocument();
 while (reader.Read())
 {
    switch (reader.NodeType)
    {
         case XmlNodeType.Element:
         if (reader.Name == "svg")
         {
            writer.WriteStartElement(reader.Name);
            while(reader.MoveToNextAttribute()){
                 writer.WriteAttributes(reader, true);
            }
         }
         if (reader.Name == "rect" || reader.Name == "polygon")
         {
            while(reader.MoveToNextAttribute()){
                 if(reader.Name == "fill" && reader.value == "none"){
                     writer.WriteStartElement(reader.Name);
                     writer.WriteAttributes(reader, true);
                     writer.WriteEndElement();
                 }
            }
         }
         break;
         case XmlNodeType.EndElement:
              break;

         default:
              break;
    }
 }
 writer.WriteEndElement();
 writer.WriteEndDocument();
 writer.Close();

但返回一个包含“fill”元素且没有“x”和“y”属性的文件(因为 WriteAttributes 从当前位置读取并且读取器位于 fill 属性中)

 <svg>
     <fill="none" stroke="#000000" stroke-width="0.2894" width="36.6" height="42.2"/>
 </svg>

是否有一种获得的方法我想要的结果?我不想使用 XmlDocument 因为我的 svg 文件很大并且需要很长时间才能使用 XmlDoc.Load 加载,

谢谢

I'm reading an svg/xml with XmlTextReader and I want to write just some of its elements back in a new svg/xml file

<svg>
    <rect x="135.7" y="537.4" fill="none" stroke="#000000" stroke-width="0.2894" width="36.6" height="42.2"/>
    <rect x="99" y="537.4" fill="#A0C9EC" stroke="#000000" stroke-width="0.2894" width="36.7" height="42.2"/>
</svg>

I want the rect elements that are filled with "none" so I started reading and writing

 var reader = new XmlTextReader(file.InputStream);
 var writer = new XmlTextWriter(svgPath + fileNameWithoutExtension + "-less" + extension, null);
 writer.WriteStartDocument();
 while (reader.Read())
 {
    switch (reader.NodeType)
    {
         case XmlNodeType.Element:
         if (reader.Name == "svg")
         {
            writer.WriteStartElement(reader.Name);
            while(reader.MoveToNextAttribute()){
                 writer.WriteAttributes(reader, true);
            }
         }
         if (reader.Name == "rect" || reader.Name == "polygon")
         {
            while(reader.MoveToNextAttribute()){
                 if(reader.Name == "fill" && reader.value == "none"){
                     writer.WriteStartElement(reader.Name);
                     writer.WriteAttributes(reader, true);
                     writer.WriteEndElement();
                 }
            }
         }
         break;
         case XmlNodeType.EndElement:
              break;

         default:
              break;
    }
 }
 writer.WriteEndElement();
 writer.WriteEndDocument();
 writer.Close();

but that returns a file with "fill" elements and no "x" and "y" attributes (because the WriteAttributes read from the current position and the reader is in the fill attribute)

 <svg>
     <fill="none" stroke="#000000" stroke-width="0.2894" width="36.6" height="42.2"/>
 </svg>

Is there a way to get the result I want? I don't want to use XmlDocument since my svg files are large and take a long time to load with XmlDoc.Load

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

椒妓 2025-01-03 16:11:35

尝试以下操作;您可以适应:

     if (reader.Name == "rect" || reader.Name == "polygon") 
     { 
           string fill = reader.GetAttribute("fill"); //Read ahead for the value of the fill attr
           if(String.Compare(fill, "none", StringComparison.InvariantCultureIgnoreCase) == 0) //if the value is what we expect then just wholesale copy this node.
           {
                writer.WriteStartElement(reader.Name);
                writer.WriteAttributes(reader, true); 
                writer.WriteEndElement(); 
            } 
        } 

请注意, GetAttribute 不会移动阅读器,允许您留在矩形或多边形节点的上下文中。

您也可以尝试使用单个 reader.MoveToFirstAttribute() 修改您的第一次尝试 - 我还没有测试过,但它应该将您移回当前节点的第一个元素。

内存中,因此可能不合适 - 选择所需的节点就只是使用 XPath 的情况:

//rect[@fill='none'] || //polygon[@fill='none'] 

您可能还想研究 XPathDocument 类 - 这比 XmlDocument 轻得多,但您仍然首先将整个结构加载到 ,您还可以使用 XSLT。如果您想为您的源文档发布更完整的结构,我很乐意为您编写一个。

Try the following; you can adapt to suit:

     if (reader.Name == "rect" || reader.Name == "polygon") 
     { 
           string fill = reader.GetAttribute("fill"); //Read ahead for the value of the fill attr
           if(String.Compare(fill, "none", StringComparison.InvariantCultureIgnoreCase) == 0) //if the value is what we expect then just wholesale copy this node.
           {
                writer.WriteStartElement(reader.Name);
                writer.WriteAttributes(reader, true); 
                writer.WriteEndElement(); 
            } 
        } 

Note that GetAttribute does not move the reader, allowing you to stay in the context of the rect or polygon node.

You could probably also try revising your first attempt with a single reader.MoveToFirstAttribute() - I haven't tested that but it should move you back to the first element of the current node.

You might also want to investigate the XPathDocument class - this is a lot lighter than XmlDocument but you still load the entire structure into memory first so may not be suitable - selecting the nodes you want would then simply be a case of using the XPath:

//rect[@fill='none'] || //polygon[@fill='none'] 

Finally, you could also use an XSLT. If you wanted to post a more complete structure for your source document I'd be happy to write one for you.

镜花水月 2025-01-03 16:11:35

使用命令式 C# 是一件令人讨厌的事情,您可以考虑使用 XSLT:
http://www.w3schools.com/xsl/el_value-of.asp

This is nasty business using imperative C#, you might consider using XSLT instead:
http://www.w3schools.com/xsl/el_value-of.asp

偏爱自由 2025-01-03 16:11:35

在调用 MoveToNextAttribute 之前,您需要将 reader.Name 存储在变量中。然后,当您调用 WriteStartElement 时,请改用该值。

if (reader.Name == "rect" || reader.Name == "polygon")
{
    // get tag name here
    var tagName = reader.Name;

    while(reader.MoveToNextAttribute()){
        if(reader.Name == "fill" && reader.value == "none"){

            // write tag name here
            writer.WriteStartElement(tagName);

            writer.WriteAttributes(reader, true);
            writer.WriteEndElement();
        }
    }
}

You need to store reader.Name in a variable before you call MoveToNextAttribute. Then when you call WriteStartElement, use that value instead.

if (reader.Name == "rect" || reader.Name == "polygon")
{
    // get tag name here
    var tagName = reader.Name;

    while(reader.MoveToNextAttribute()){
        if(reader.Name == "fill" && reader.value == "none"){

            // write tag name here
            writer.WriteStartElement(tagName);

            writer.WriteAttributes(reader, true);
            writer.WriteEndElement();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文