如何根据节点数将 XML 文件拆分为多个 XML 文件
How to Split an XML file into multiple XML Files based on number of nodes
这个问题与 this one 非常相似,但有一点不同。
我正在尝试根据每个对象允许的标记元素数量将表示 xml 的对象拆分为多个 xml 对象。我正试图找到最好的方法来解决这个问题。对此的任何帮助都会很棒...关于我正在尝试做的示例...
xml 源表示:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c1</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
<Observation>
<Command>c2</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
假设每个文档允许的“Tag”元素数量为 ... 3
xml 1:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c1</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
xml 2:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c1</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
<Observation>
<Command>c2</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
我相信你现在已经知道要求是什么了,但我会继续:
xml 3:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c2</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
xml 4:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c2</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
您需要加载初始文档,然后从文档中删除 Observation
标签。循环观察标签并创建新文档,在其中添加 Observation
标签项。在 docList 中,您拥有所有新文档。
var result = doc.Root.Elements().Where(x => x.Name == "Observation").ToList();
doc.Root.Elements().Where(x => x.Name == "Observation").Remove();
List<XDocument> docList = new List<XDocument>();
foreach(var el in result)
{
XDocument d = new XDocument(doc);
d.Root.Add(el);
docList.Add(d);
}
我认为你最好的选择是为你拥有的数据建立一个模型。
public class Observation
{
public string Command { get; set; }
public List<Tag> Tags { get; set; }
}
[...] // Define also de Tag class
然后您可以使用 LINQ to XML 轻松读取 xml,使用您想要的标准处理模型并使用 LINQ to XML.[=12= 将其保存回来]
我真的觉得学习如何使用 LINQ to XML 超出了问题的范围,所以我建议你参考另一个处理它的问题:
Parse xml using LINQ to XML to class objects
请尽量不要直接将数据用作原始行然后再次保存,之后你想做的任何更改都将是一场噩梦。
XSLT 2.0(由 Saxon https://www.nuget.org/packages/Saxon-HE/ 支持)允许您将一个 XML 文档转换为多个,这是将您的输入拆分为多个文件的一种方法:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:param name="tags-per-doc" as="xs:integer" select="3"/>
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:for-each-group select="//Tag" group-adjacent="(position() - 1) idiv $tags-per-doc">
<xsl:result-document href="result{position()}.xml">
<xsl:apply-templates select="/*"/>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Observation">
<xsl:if test="current-group() intersect *">
<xsl:copy>
<xsl:apply-templates select="@*, node()[. intersect current-group() or not(self::Tag)]"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
这个问题与 this one 非常相似,但有一点不同。
我正在尝试根据每个对象允许的标记元素数量将表示 xml 的对象拆分为多个 xml 对象。我正试图找到最好的方法来解决这个问题。对此的任何帮助都会很棒...关于我正在尝试做的示例...
xml 源表示:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c1</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
<Observation>
<Command>c2</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
假设每个文档允许的“Tag”元素数量为 ... 3
xml 1:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c1</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
xml 2:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c1</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
<Observation>
<Command>c2</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
我相信你现在已经知道要求是什么了,但我会继续:
xml 3:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c2</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
xml 4:
<?xml version="1.0" encoding="utf-8"?>
<DocType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pmlcore="urn:autoid:specification:interchange:xml:schema:1">
<id>tbd</id>
<Observation>
<Command>c2</Command>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Tag>
<id>....</id>
<Data>...</Data>
</Tag>
<Data>...</Data>
</Observation>
</DocType>
您需要加载初始文档,然后从文档中删除 Observation
标签。循环观察标签并创建新文档,在其中添加 Observation
标签项。在 docList 中,您拥有所有新文档。
var result = doc.Root.Elements().Where(x => x.Name == "Observation").ToList();
doc.Root.Elements().Where(x => x.Name == "Observation").Remove();
List<XDocument> docList = new List<XDocument>();
foreach(var el in result)
{
XDocument d = new XDocument(doc);
d.Root.Add(el);
docList.Add(d);
}
我认为你最好的选择是为你拥有的数据建立一个模型。
public class Observation
{
public string Command { get; set; }
public List<Tag> Tags { get; set; }
}
[...] // Define also de Tag class
然后您可以使用 LINQ to XML 轻松读取 xml,使用您想要的标准处理模型并使用 LINQ to XML.[=12= 将其保存回来]
我真的觉得学习如何使用 LINQ to XML 超出了问题的范围,所以我建议你参考另一个处理它的问题: Parse xml using LINQ to XML to class objects
请尽量不要直接将数据用作原始行然后再次保存,之后你想做的任何更改都将是一场噩梦。
XSLT 2.0(由 Saxon https://www.nuget.org/packages/Saxon-HE/ 支持)允许您将一个 XML 文档转换为多个,这是将您的输入拆分为多个文件的一种方法:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:param name="tags-per-doc" as="xs:integer" select="3"/>
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:for-each-group select="//Tag" group-adjacent="(position() - 1) idiv $tags-per-doc">
<xsl:result-document href="result{position()}.xml">
<xsl:apply-templates select="/*"/>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Observation">
<xsl:if test="current-group() intersect *">
<xsl:copy>
<xsl:apply-templates select="@*, node()[. intersect current-group() or not(self::Tag)]"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>