我有一个带有嵌套元素/节点的XML文件。我需要<proceduralStep>
为每个节点及其子节点增加属性“ id”。我的第一个问题是我无法使用来更改属性 node.Attributes("id").Value = node.Attributes("id").Value + 1
。它在上给出了错误node.Attributes("id").Value +1
。这是父元素/proceduralStep/
。第二个问题是,如果它是的子元素,则需要更改每个节点属性<proceduralStep>
。因此,如果/proceduralStep/proceduralStep
属性ID更改为1.1。我一直在网上搜索有关如何执行此操作的示例和说明,但没有找到任何可行的方法。
样本XML
<dmodule>
<mainProcedure>
<proceduralStep id="step1">
<para>Step 1</para>
</proceduralStep>
<proceduralStep id="step2">
<figure id="fig2">
<title>xxxxx</title>
<graphic infoEntityIdent="ICN-GAASI"></graphic>
</figure>
</proceduralStep>
<proceduralStep id="step3">
<para>Step 3 with link to step 2 (ID 23) here:
<internalRef internalRefId="step2" internalRefTargetType="step"></internalRef></para>
<figure id="fig3">
<title>xxxxx</title>
<graphic infoEntityIdent="ICN-GAASIB0"></graphic>
</figure>
<proceduralStep id="step3.1">
<para>Step 3.2 with link to step 3.1 (ID 23a) here:
<internalRef internalRefId="step3.1" internalRefTargetType="step"></internalRef></para>
</proceduralStep>
<proceduralStep id="step3.2">
<figure>
<title>xxxxx</title>
<graphic infoEntityIdent="ICN-GAASIB0-00-"></graphic>
</figure>
<proceduralStep id="step3.2.1">
<figure>Step 3.3.1</figure>
</proceduralStep>
<proceduralStep id="step3.2.2">
<para>Step 3.3.2 with link to step 3.3.1 (ID 23c1) here:
<internalRef internalRefId="step3.2.1" internalRefTargetType="step"></internalRef></para>
</proceduralStep>
<proceduralStep id="step3.2.3">
<figure>Step 3.3.3</figure>
</proceduralStep>
</proceduralStep>
</proceduralStep>
</mainProcedure>
</dmodule>
无效的代码
Dim doc As XDocument = XDocument.Load(FILENAME)
Dim directoryName As String = Path.GetDirectoryName(FILENAME)
Dim root As XElement = doc.Root
Dim prefixStep As String = "step"
Dim prefixFig As String = "fig"
Dim nameResult As String = Path.GetFileName(FILENAME)
Dim ns As XNamespace = root.GetDefaultNamespace()
Dim mainProcedure As XElement = root.Descendants("mainProcedure").FirstOrDefault()
RenumberStep(mainProcedure, prefixStep, ns)
RenumberFigures(mainProcedure, prefixFig, ns)
For Each internalRef As XElement In doc.Descendants(ns + "internalRef")
Dim oldId As String = CType(internalRef.Attribute("internalRefId"), String)
If Not oldId Is Nothing Then
If dictionary.ContainsKey(oldId) Then
internalRef.SetAttributeValue("internalRefId", dictionary(oldId))
Else
' internalRef.SetAttributeValue("internalRefId", "Error : " & oldId)
End If
End If
Next internalRef
doc.Save(FILENAME)
Module Module1
Public dictionary As New Dictionary(Of String, String)
Public dictionaryFig As New Dictionary(Of String, String)
Sub RenumberStep(parent As XElement, prefix As String, ns As XNamespace)
Dim index As Integer = 1
For Each proceduralStep As XElement In parent.Elements(ns + "proceduralStep")
Dim oldId = CType(proceduralStep.Attribute("id"), String)
If Not oldId Is Nothing Then
dictionary.Add(oldId, prefix + index.ToString())
proceduralStep.SetAttributeValue("id", prefix + index.ToString())
RenumberStep(proceduralStep, prefix + index.ToString() + ".", ns)
Else
proceduralStep.SetAttributeValue("id", prefix + index.ToString())
End If
index = index + 1
Next proceduralStep
End Sub
Sub RenumberFigures(parent As XElement, prefix As String, ns As XNamespace)
Dim index As Integer = 1
For Each figure As XElement In parent.Elements(ns + "figure")
Dim oldfigId = CType(figure.Attribute("id"), String)
If Not oldfigId Is Nothing Then
dictionaryFig.Add(oldfigId, prefix + index.ToString())
figure.SetAttributeValue("id", prefix + index.ToString())
RenumberFigures(figure, prefix + index.ToString() + ".", ns)
Else
figure.SetAttributeValue("id", prefix + index.ToString())
End If
index = index + 1
Next figure
End Sub
End Module
使用递归算法和xml linq真正简单:
Module Module1
Const FILENAME As String = "c:\temp\test.xml"
Const OUTPUT_FILENAME As String = "c:\temp\test1.xml"
Public dictionary As New Dictionary(Of String, String)
Sub Main()
Dim doc As XDocument = XDocument.Load(FILENAME)
Dim root As XElement = doc.Root
Dim ns As XNamespace = root.GetDefaultNamespace()
Dim mainProcedure As XElement = root.Descendants("mainProcedure").FirstOrDefault()
Dim prefix As String = "step"
Renumber(mainProcedure, prefix, ns)
For Each internalRef As XElement In doc.Descendants(ns + "acronymTerm")
Dim oldId As String = CType(internalRef.Attribute("internalRefId"), String)
If Not oldId Is Nothing Then
If dictionary.ContainsKey(oldId) Then
internalRef.SetAttributeValue("internalRefId", dictionary(oldId))
Else
internalRef.SetAttributeValue("internalRefId", "Error : " & oldId)
End If
End If
Next internalRef
doc.Save(OUTPUT_FILENAME)
End Sub
Sub Renumber(parent As XElement, prefix As String, ns As XNamespace)
Dim index As Integer = 1
For Each proceduralStep As XElement In parent.Elements(ns + "proceduralStep")
Dim oldId = CType(proceduralStep.Attribute("id"), String)
dictionary.Add(oldId, prefix + index.ToString())
proceduralStep.SetAttributeValue("id", prefix + index.ToString())
Renumber(proceduralStep, prefix + index.ToString() + ".", ns)
index = index + 1
Next proceduralStep
End Sub
End Module
输出量
<?xml version="1.0" encoding="utf-8"?>
<dmodule xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.s1000d.org/S1000D_4-0-1/xml_schema_flat/proced.xsd">
<mainProcedure>
<proceduralStep id="step1">
<para>XX xxx<acronym id="mosim">XX xxx<acronymTerm>XX xxx</acronymTerm>XX xxx<acronymDefinition>XX xxx</acronymDefinition>XX xxx</acronym>XX xxx<internalRef internalRefId="Error : Error : fig1" internalRefTargetType="figure" targetTitle="fig1">XX xxx</internalRef>XX xxx</para>
<proceduralStep id="step1.1">
<para>XX xxx</para>
</proceduralStep>
<proceduralStep id="step1.2">
<para>XX xxx<acronymTerm internalRefId="mosim">XX xxx</acronymTerm>XX xxx</para>
</proceduralStep>
<proceduralStep id="step1.3">
<para>XX xxx</para>
</proceduralStep>
</proceduralStep>
<proceduralStep id="step2">
<para>XX xxx<acronymTerm internalRefId="mosim">XX xxx</acronymTerm>XX xxx<internalRef internalRefId="Error : Error : fig1" internalRefTargetType="figure" targetTitle="fig1">XX xxx</internalRef>XX xxx</para>
<proceduralStep id="step2.1">
<para>XX xxx<acronymTerm internalRefId="mosim">XX xxx</acronymTerm>XX xxx</para>
</proceduralStep>
<proceduralStep id="step2.2">
<para>XX xxx<acronymTerm internalRefId="mosim">XX xxx</acronymTerm>XX xxx</para>
</proceduralStep>
</proceduralStep>
<proceduralStep id="step3">
<para>XX xxx<emphasis>XX xxx</emphasis>XX xxx</para>
</proceduralStep>
<proceduralStep id="step4">
<para>XX xxx<emphasis>XX xxx</emphasis>XX xxx</para>
</proceduralStep>
<proceduralStep id="step5">
<para>XX xxx<acronymTerm internalRefId="lola">XX xxx</acronymTerm>XX xxx<acronym id="cd">XX xxx<acronymTerm>XX xxx</acronymTerm>XX xxx<acronymDefinition>XX xxx</acronymDefinition>XX xxx</acronym>XX xxx<acronymTerm internalRefId="mosim">XX xxx</acronymTerm>XX xxx<acronymTerm internalRefId="cd">XX xxx</acronymTerm>XX xxx<acronym id="dvd">XX xxx<acronymTerm>XX xxx</acronymTerm>XX xxx<acronymDefinition>XX xxx</acronymDefinition>XX xxx</acronym>XX xxx</para>
</proceduralStep>
</mainProcedure>
</dmodule>
谢谢你的代码。您的示例满足了我的需要,除了'internalRef'并没有更改refID(它仍然显示为“ step23c1”)。您的代码看起来像是在C语言中,是否可以在VB.Net中重新获得代码?我不熟悉C并迷路于其中。谢谢你仁
我尝试将您的代码放入C#文件中,但是收到以下错误“有多个根元素。第4行,位置2”。由于我不知道C,所以我无所适从。@jdweng
我将代码更改为VB.Net,并添加了行以保存输出。
谢谢@jdweng
internalRefID的步骤已作为goto的idRefef被引用,但它应该是最初引用的ID。因此,步骤3.3.2的内部引用ID为步骤3.3.1,并且refID指向步骤3.3.1。我知道这不是最好的解释。但是尝试简单地说,每个internalRefId都有它引用的过程步骤ID。运行代码后,那些internalRefId现在会显示其引用的过程步骤ID,而不是链接到的internalRefId。