【问题标题】:modify/beutify XML file or tags using vbscript?使用 vbscript 修改/美化 XML 文件或标签?
【发布时间】:2015-03-17 07:54:43
【问题描述】:

我有一个格式如下的 XML 文件:

<payments/>
    <payment>
        <payment_type>
        </payment_type>
        <dataforpay>
        </dataforpay>
        <allocations/>
            <allocation>
                <id>
                </id>
                <notfind>
                </notfind>
                <amount>
                </amount>
            </allocation>
    </payment>

因为它看起来很高级的格式,我想用 vbscript 把这个格式更新到下面.....请给建议?

<payments>
    <payment>
        <payment_type>
        </payment_type>
        <dataforpay>
        </dataforpay>
        <allocations>
            <allocation>
                <id>
                </id>
                <notfind>
                </notfind>
                <amount>
                </amount>
            </allocation>
        </allocations>
    </payment>
</payments>

【问题讨论】:

  • 您是否在问,例如将&lt;payments/&gt;&lt;payment/&gt; 更改为&lt;payments&gt;&lt;payment/&gt; ... &lt;/payments&gt;
  • 是的,但不是每次都这样。在一个节点中,它的 应该是 ......... .. 但 节点的格式已经正确。

标签: xml vbscript xsd xml-parsing


【解决方案1】:

试试下面的代码。它找到名称为复数形式的自闭标签,后跟一对或多对具有相同名称的单数开闭标签,并将每个自闭标签替换为开闭对,并移入其中以下所有匹配的标签。

sCont = ReadTextFile("C:\Test\src.xml", -2)

With CreateObject("VBScript.RegExp")
    .Global = False
    .MultiLine = True
    .IgnoreCase = True
    Do
        ' pattern to match a self-closing tag with name in the plural followed by one or more pair of open-close tags with the same name in the singular
        .Pattern = "^[\r\n]*(\s*)<(\w+)s(\s+[^>]*)*/\s*>(\s*[\r\n]+)(\s*<\2(?:\s+[^>]*)*>[\s\S]*?</\2>)"
        If Not .Test(sCont) Then Exit Do
        ' replace matched self-closing tag with open-close pair, and moves first matched following tag into it 
        sCont = .Replace(sCont, "$1<$2s$3>$4$5$4$1</$2s>")
        ' pattern to match a pair of open-close tags with name in the plural containing one or more, and followed by one or more pair of open-close tags with the same name in the singular
        .Pattern = "((?:^\s*)<(\w+)s(?:\s+[^>]*)*>\s*[\r\n]+\s*<\2(?:\s+[^>]*)*>[\s\S]*?</\2>\s*[\r\n]+)(^\s*</\2s>\s*[\r\n]+)(\s*<\2(?:\s+[^>]*)*>[\s\S]*?</\2>\s*[\r\n]+)"
        Do While .Test(sCont)
            ' move matched tag with the same name in the singular into
            sCont = .Replace(sCont, "$1$4$3")
        Loop
    Loop
End With

WriteTextFile sCont, "C:\Test\dst.xml", -2

Function ReadTextFile(sPath, iFormat)
    With CreateObject("Scripting.FileSystemObject").OpenTextFile(sPath, 1, False, iFormat)
        ReadTextFile = ""
        If Not .AtEndOfStream Then ReadTextFile = .ReadAll
        .Close
    End With
End Function

Sub WriteTextFile(sCont, sPath, iFormat)
    With CreateObject("Scripting.FileSystemObject").OpenTextFile(sPath, 2, True, iFormat)
        .Write(sCont)
        .Close
    End With
End Sub

请参阅使用 RegExp disclaimer 进行 XHTML 解析。

【讨论】:

  • 嗨,我们如何将 '&' 更改/替换为 '&'对于 sCont。我收到“解析错误:应使用分号字符”。使用此功能时。
  • 你可以不用正则表达式,使用sCnt = Replace(sCnt, "&amp;", "&amp;amp;")
【解决方案2】:

原始格式不是有效的 XML,因为它有 2 个根节点,所以我使用标准 Scripting.FileSystemObject 加载了文件,以防止 XML 解析错误产生任何错误

Option Explicit

dim fso: set fso = CreateObject("Scripting.FileSystemObject")
dim stream: set stream = fso.OpenTextFile("input.xml")
dim xml: xml = stream.ReadAll()
stream.close

为了操作 XML,我将它加载到带有虚拟根节点的 MSXML2.DomDocument 中,因此它的格式正确

dim xmldoc: set xmldoc = CreateObject("MSXML2.DomDocument")
xmldoc.setProperty "SelectionLanguage", "XPath"
xmldoc.async = false
if not xmldoc.loadXML("<root>" & xml & "</root>") then
    WScript.Echo xmldoc.parseError.reason
    WScript.Quit
end if

然后我使用XPath查询payments节点(假设只有一个)和payment节点(假设不止一个)

dim paymentsNode: set paymentsNode = xmldoc.selectSingleNode("//payments")
dim paymentNodes: set paymentNodes = xmldoc.selectNodes("//payment")

然后我遍历每个支付节点,然后查询allocations 节点(假设只有一个)和allocation 节点(假设不止一个)。每个allocation 节点都从其父节​​点中删除并添加到allocations 节点。然后对payment 进行相同操作。

dim p
for p = 0 to paymentNodes.length - 1
    dim payment: set payment = paymentNodes.Item(p)
    dim allocationsNode: set allocationsNode = payment.selectSingleNode("./allocations")
    dim allocationNodes: set allocationNodes = payment.selectNodes("./allocation")

    dim a
    for a = 0 to allocationNodes.length - 1
        dim allocation: set allocation = allocationNodes.Item(a)
        allocation.parentNode.removeChild allocation
        allocationsNode.appendChild allocation
    next

    payment.parentNode.removeChild payment
    paymentsNode.appendChild payment
next

因为payments 节点现在是一个有效的根节点,我将payment 级别的XML 重新加载到xmldoc 对象中,以在保存到磁盘之前删除我们的临时root 节点。

xmldoc.loadXML xmldoc.selectSingleNode("/root/payments").xml
xmldoc.save "output.xml"

直接节点操作的替代方法是使用XSL Transform,但同样,您需要更正根节点。如果您的输入 XML 文件很大,这可能是一个更好的选择。

【讨论】:

  • 感谢您的帮助。很高兴知道这一点。就我而言,我有很多节点的大文件。其中有些是良好的甲酸盐,有些则不是。我只是举了支付节点的例子。我确实有很多与支付节点相同的不同节点。我需要为所有节点和所有文件执行此操作吗?它可能会失败,因为某些文件的格式也正确。因此,如果他们像您建议 XSL Transform 那样采用任何方式,那么请帮我听听。
猜你喜欢
  • 2014-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 2014-08-03
  • 2023-03-04
  • 1970-01-01
  • 2013-09-21
相关资源
最近更新 更多