【发布时间】:2021-12-24 01:11:10
【问题描述】:
我正在尝试重构现有工具以减少内存使用量。该工具会处理一个 XML 文件,该文件的开头如下:
<?xml version="1.0" encoding="utf-8"?>
<XQ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="my.xsd" SchemaVersion="2.0" SoftwareVersion="2.10.6.195" ExportMode="StrongReferences" System="foo" Database="bar" Description="descriptio of bar database on foo system" Created="2021-11-10T15:14:57.8590869Z" id="9632241b-2b2b-46a4-81b0-fb9bd65c2ef5" ParentKey="a743efc8-7095-4791-b44c-da70bb01f075" ExportedObject="wibble" ExportedType="baz" Identity="bif" Persist="142 {9895150E-085D-4fcb-A16D-5EF5D2527196} 2\{a743efc8-7095-4791-b44c-da70bb01f075}\{9632241b-2b2b-46a4-81b0-fb9bd65c2ef5}*foo\bar">
<APDatabase>
<id>11111111-2222-3333-4444-555555555555</id>
<Name>foo</Name>
<Description>foo database</Description>
<APAttCat>
<id>22222222-2222-2222-2222-222222222222</id>
<Name>just a name</Name>
</APAttCat>
<APElemTemp>
<id>6012ede0-c202-4474-a13a-d9cc349c638e</id>
<Name>name of this elem temp</Name>
<Description>description of this elem temp</Description>
<BaseTemplateOnly>false</BaseTemplateOnly>
<Type>None</Type>
<InstanceType>Elem</InstanceType>
<AllowElemToExtend>true</AllowElemToExtend>
<APAttTemp>
<id>33333333-3333-3333-3333-333333333333</id>
<Name>Name of this att temp</Name>
<Description>Description of this att temp</Description>
<Type>String</Type>
<Value type="String"></Value>
<AttCatRef id="44444444-4444-4444-4444-444444444444">!Configuration</AttCatRef>
</APAttTemp>
</APElemTemp>
...
这些文件中还有很多内容,最终可能会变得庞大。重要的方面是每个<AP...> XML 元素的第一个子元素是一个<id> 元素,其中包含该父元素的guid。当前程序将整个内容加载到 XDocument 中,并向所有 '<id> 元素不存在于单独的 guid 列表中,然后保存到另一个文件。
例如,如果 APAttTemp (33333333-3333-3333-3333-333333333333) 的 guid 不在我单独的 guid 列表中,我需要写 <APAttTemp delete="true">。
但是将整个内容加载到内存中会导致问题。我想做同样的事情,但不将整个 xml 加载到内存中。我可以用 XmlReader/XmlWriter 做到这一点吗?有没有更好的办法?
我是 XML 处理的新手,但到目前为止,我有一个阅读器和编写器来打开源 XML 并复制它。
正如@dbc 所说,需要提前查看子<id> 元素以发现当前元素是否需要修改。我在想也许我可以缓存任何<AP...> 元素并读取下一个<id> 元素,然后再将它们都写入输出?
【问题讨论】:
-
能否请您edit 澄清您要从显示的输入 XML 生成的 XML?例如。您想将
<Name>转换为<Name delete="true">,因为<Name>没有<id>子元素,但您不想将它添加到<ElemTemp>,因为它有?那么<AttCatRef id="44444444-4444-4444-4444-444444444444">呢?显然你不能删除根元素,但它会有<id>子元素吗? -
在没有 minimal reproducible example 的情况下,我的猜测是你需要通过文件两次,因为 1)
XmlReader和XmlWriter是只转发的,但是 2) 你希望在扫描其子元素以查找<id>元素后向元素添加属性,这意味着您需要从当前阅读器位置向后写。 -
<id>元素是否总是 first 子元素? -
嗨@dbc,是的,
<id>始终是第一个元素
标签: xml linq-to-xml xmlreader xmlwriter