XML文件输出仅显示字节顺序标记 [英] XML file output only shows Byte Order Mark

查看:126
本文介绍了XML文件输出仅显示字节顺序标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个我正在解析的XML文件,其内容正是以下XML:

I have an XML file that I am trying to parse, whose contents are exactly the XML below:

<Results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Reference>{REFERENCE-HERE}</Reference>
  <FillerTags>Filler</FillerTags>
  <entity>
    <entityName>ABC</entityName>
    <entityId>012345</entityId>
  </entity>
  <Items>
     <Item>
      <FillerTagsAgain>Filler2</FillerTagsAgain>
      <FillerTagsAgain>Filler2</FillerTagsAgain>
      <FillerTagsAgain>Filler2</FillerTagsAgain> 
     </Item>
     <AnotherItem> 
       <FillerTagsAgain>Filler2</FillerTagsAgain>
       <FillerTagsAgain>Filler2</FillerTagsAgain>
       <FillerTagsAgain>Filler2</FillerTagsAgain> 
     </AnotherItem>
   </Items>
</Results>

我一直在尝试获取下面的代码(最初来自我的这里有疑问)上班。其他几个用户(包括代码的创建者)已经能够成功使用它,但是当我运行它时,输出文件只是以ÿþ出来。我确保将文件编码为ANSI,并将记事本文件立即保存为.xml,但输出仍然只有字节顺序标记。

I have been trying to get the code below (initially from my question here) to work. Several other users (including the code's creator) have been able to use it successfully, but when I run it the output file simply comes out as ÿþ<. I made sure to encode the file as ANSI and immediately save the Notepad file as .xml but the output still only has the byte order mark.

Option Explicit
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub ParseResults()
'Requires reference to Microsoft XML, v6.0
'Requires referenc to Microsoft Scripting Runtime
Dim xmlFilePath$, newFilePath$
Dim DOM As MSXML2.DOMDocument
Dim entity As IXMLDOMNode
Dim fso As Scripting.FileSystemObject

'# Define the file you are going to load as XML
xmlFilePath = "PATH"

'# Define an output path for where to put the modified XML
newFilePath = "NEWPATH"

'# Create our DOM object
Set DOM = CreateObject("MSXML2.DOMDocument")

'# Load the XML file
DOM.Load xmlFilePath

'# Wait until the Document has loaded
Do
    Sleep 250
Loop Until DOM.readyState = 4

'# Get the entityID node
Set entity = DOM.DocumentElement.getElementsByTagName("entityId")(0)

'# Call a subroutine to append the entity to "Item" tags
AppendEntity DOM, "Item", entity
'# Call a subroutine to append the entity to "AnotherItem" tags
AppendEntity DOM, "AnotherItem", entity

'## Create an FSO to write the new file
Set fso = CreateObject("Scripting.FileSystemObject")

'## Attempt to write the new/modified XML to file
On Error Resume Next
fso.CreateTextFile(newFilePath, True, True).Write DOM.XML
If Err Then
    '## Print the new XML in the Immediate window
    Debug.Print DOM.XML
    MsgBox "Unable to write to " & newFilePath & " please review XML in the Immediate window in VBE.", vbInformation
    Err.Clear
End If
On Error GoTo 0

'Cleanup
Set DOM = Nothing
Set fso = Nothing
Set entity = Nothing

End Sub

Sub AppendEntity(DOM As Object, tagName As String, copyNode As Object)
'## This subroutine will append child node to ALL XML Nodes matching specific string tag.
Dim itemColl As IXMLDOMNodeList
Dim itm As IXMLDOMNode

'# Get a collection of all elements matching the tagName
Set itemColl = DOM.DocumentElement.getElementsByTagName(tagName)

'# Iterate over the collection, appending the copied node
For Each itm In itemColl
    If itm.HasChildNodes Then
        '# Insert this node before the first child node of Item
        itm.InsertBefore copyNode.CloneNode(True), itm.FirstChild
    Else
        '# Append this node to the Item
        itm.appendChild copyNode.CloneNode(True)
    End If
Next

Set itm = Nothing
Set itemColl = Nothing

End Sub

可以肯定的是,代码不会产生错误 - 它会创建一个新文件,但是它创建的文件不正确。正确的输出应该是(并且对于已经尝试过此代码的其他人):

To be sure, the code produces no errors - it creates a new file, but the file it creates is incorrect. The correct output should be (and is for some others who have tried this code) this:

<Results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Reference>{REFERENCE-HERE}</Reference>
  <FillerTags>Filler</FillerTags>
  <entity>
    <entityName>ABC</entityName>
    <entityId>012345</entityId>
  </entity>
  <Items>
    <Item>
      <entityId>012345</entityId>
      <FillerTagsAgain>Filler2</FillerTagsAgain>
      <FillerTagsAgain>Filler2</FillerTagsAgain>
      <FillerTagsAgain>Filler2</FillerTagsAgain> 
     </Item>
     <AnotherItem> 
       <entityId>012345</entityId>
       <FillerTagsAgain>Filler2</FillerTagsAgain>
       <FillerTagsAgain>Filler2</FillerTagsAgain>
       <FillerTagsAgain>Filler2</FillerTagsAgain> 
     </AnotherItem>
   </Items>

就是说,代码插入每个标签的子节点。在我正在寻求应用此代码的真正的XML文档中,我可以让它在这个示例上工作,XML是一样的,但包含多个实体。例如:

That is, the code inserts the as a child node of each tag. In the real XML document that I am looking to apply this code to after I can get it to work on this example XML is much the same, but contains multiple entities. For example:

   <Results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Reference>{REFERENCE-HERE}</Reference>
      <FillerTags>Filler</FillerTags>
      <entity>
        <entityName>ABC</entityName>
        <entityId>012345</entityId>
      </entity>
      <Items>
        <Item>
          <entityId>012345</entityId>
          <FillerTagsAgain>Filler2</FillerTagsAgain>
          <FillerTagsAgain>Filler2</FillerTagsAgain>
          <FillerTagsAgain>Filler2</FillerTagsAgain> 
         </Item>
         <AnotherItem> 
           <entityId>012345</entityId>
           <FillerTagsAgain>Filler2</FillerTagsAgain>
           <FillerTagsAgain>Filler2</FillerTagsAgain>
           <FillerTagsAgain>Filler2</FillerTagsAgain> 
         </AnotherItem>
       </Items>
     <entity>
      <entityName>DEF</entityName>
        <entityId>678910</entityId>
      </entity>
      <Items>
        <Item>
          <entityId>678910</entityId>
          <FillerTagsAgain>Filler2</FillerTagsAgain>
          <FillerTagsAgain>Filler2</FillerTagsAgain>
          <FillerTagsAgain>Filler2</FillerTagsAgain> 
         </Item>
         <AnotherItem> 
           <entityId>678910</entityId>
           <FillerTagsAgain>Filler2</FillerTagsAgain>
           <FillerTagsAgain>Filler2</FillerTagsAgain>
           <FillerTagsAgain>Filler2</FillerTagsAgain> 
         </AnotherItem>
       </Items>   

非常感谢任何解决问题的帮助。

Any help troubleshooting this problem would be much appreciated.

更新:

上面的代码通过更改行 fso.CreateTextFile(newFilePath,True,True).Write DOM起作用。 XML to fso.CreateTextFile(newFilePath,True,False).Write DOM.XML

The code above now works by changing the line fso.CreateTextFile(newFilePath, True, True).Write DOM.XML to fso.CreateTextFile(newFilePath, True, False).Write DOM.XML.

我现在正试图在较大的一组XML数据上运行此代码,但在线路上收到错误Set entity = DOM.DocumentElement.getElementsByTagName (entityId)(0)

I am now attempting to run this on the larger set of XML data but receive an error on the line Set entity = DOM.DocumentElement.getElementsByTagName("entityId")(0)

我在示例文件中有这个错误几次,意识到我刚刚忘记设置正确的目录,但是尽管确保目录正确,这次错误仍然存​​在。

I had this error on the example file a few times and realized I had just forgotten to set the correct directory, but despite ensuring the directory is correct this time the error persists.

更新2:我收到此错误的代码已修改如下。如果我没有错,我所做的是重命名几件事,但是我可能会错了。

UPDATE 2: The code I am receiving this error on has been modified as below. If I'm not mistaken all I did was rename a few things, but I may be wrong.

Option Explicit
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub ParseResults()
'Requires reference to Microsoft XML, v6.0
'Requires referenc to Microsoft Scripting Runtime
Dim xmlFilePath$, newFilePath$
Dim DOM As MSXML2.DOMDocument
Dim Customer As IXMLDOMNode
Dim fso As Scripting.FileSystemObject

'# Define the file you are going to load as XML
xmlFilePath = "C:\FAKEPATH\Final_Test.xml"

'# Define an output path for where to put the modified XML
newFilePath = "C:\FAKEPATH\Final_Test1.xml"

'# Create our DOM object
Set DOM = CreateObject("MSXML2.DOMDocument.6.0")

'# Load the XML file
DOM.Load xmlFilePath

'# Wait until the Document has loaded
Do
    Sleep 250
Loop Until DOM.readyState = 4

'# Get the entityID node
Set Customer = DOM.DocumentElement.getElementsByTagName("CustomerId")(0)

'# Call a subroutine to append the entity to "Item" tags
AppendCustomer DOM, "Transaction", Customer

'## Create an FSO to write the new file
Set fso = CreateObject("Scripting.FileSystemObject")

'## Attempt to write the new/modified XML to file
On Error Resume Next
'MsgBox DOM.XML
fso.CreateTextFile(newFilePath, True, False).Write DOM.XML
If Err Then
    '## Print the new XML in the Immediate window
    Debug.Print DOM.XML
    MsgBox "Unable to write to " & newFilePath & " please review XML in the Immediate window in VBE.", vbInformation
    Err.Clear
End If
On Error GoTo 0

'Cleanup
Set DOM = Nothing
Set fso = Nothing
Set Customer = Nothing

End Sub

Sub AppendCustomer(DOM As Object, Transaction As String, copyNode As Object)
'## This subroutine will append child node to ALL XML Nodes matching specific string tag.
Dim itemColl As IXMLDOMNodeList
Dim itm As IXMLDOMNode

'# Get a collection of all elements matching the tagName
Set itemColl = DOM.DocumentElement.getElementsByTagName(Transaction)

'# Iterate over the collection, appending the copied node
For Each itm In itemColl
    If itm.HasChildNodes Then
        '# Insert this node before the first child node of Item
        itm.InsertBefore copyNode.CloneNode(True), itm.FirstChild
    Else
        '# Append this node to the Item
        itm.appendChild copyNode.CloneNode(True)
    End If
Next

Set itm = Nothing
Set itemColl = Nothing

End Sub

更新3:一切现在都可以完美运行。唯一的问题是在上面的代码所执行的实际过程中。由于存在多个实体,并且每组项目属于一个实体,所以代码需要找到一个entityId,并将此entityId应用于在另一个entityId标签发生之前的所有项目。在这一点之后,一切都会重演。

UPDATE 3: Everything now works perfectly. The only issue is in the actual procedure pursued by the code above. Since there are multiple entities, and each set of items belongs to an entity, the code needs to find an entityId and apply this entityId to all the items that come BEFORE another occurrence of an entityId tag. After this point everything would repeat.

推荐答案

我把这个放在最初,作为一个答案,所以我可以清楚地显示我的代码。如果这也会失败会删除。尝试这种语法来使用替代方法来写入文件。 Notepadd ++告诉我这是ANSII:

I'm putting this here initially as an answer so I can show my code legibly. Will delete if this also fails. Try this syntax to use the alternative method of writing the file. Notepadd++ tells me this is ANSII:

'## Create an FSO to write the new file'
Set fso = CreateObject("Scripting.FileSystemObject")


Dim FF As Integer
FF = FreeFile
'## Attempt to write the new/modified XML to file'
fso.CreateTextFile newFilePath
Open newFilePath For Output As FF
Print #FF, dom.XML
Close #FF

(再次,只是覆盖基础,并将更新或删除如果需要)

(again, just covering the bases, and will update or remove if needed)

尝试:

fso.CreateTextFile(newFilePath, True, False).Write DOM.XML

区别在于 CreateTextFile 方法指定是否将文件创建为Unicode( True )或ASCII( False )。

The difference being the third argument in the CreateTextFile method specifies whether to create the file as Unicode (True) or ASCII (False).

记事本++确认这个方法是ANSII,而如果我做 True 来创建Unicode文件,我得到一个UCS- 2个小Endian文件。

Notepad++ confirms this method is ANSII, whereas if I do True to create Unicode file, I get a UCS-2 Little Endian file.

我个人没有注意到Ascii / Unicode之间没有区别 - 我可以在记事本或记事本++中打开它们,并且对我来说也是一样的,但是这似乎是一个字符编码问题,值得一试。我建议它仅仅是第一个(最简单的)实现的选项(如果需要,还有更多的选择可以探索)。

I personally notice no difference between either Ascii/Unicode -- I can open both in Notepad or Notepad++ and they appear the same to me, but since this seems like it could be a character-encoding issue, it is worth a shot. I suggested it only as the first (and easiest) option to implement (there are some more options to explore if needed).

更新#3

为了解决文件的嵌套本质...基本上你有XML元素(entity和Item),您需要修改Item(它是子节点)以包含entityId(它是entity的子节点)。我正在解释这种关系,希望这个修改是有道理的!

To address the nested nature of the file... basically you have XML element siblings ("entity" and "Item"), and you need to modify the "Item" (and it's child nodes) to include the "entityId" (which is a child of "entity"). I'm explaining this relationship so that hopefully this modification makes sense!

'##### NO LONGER USED:'
'# Get the entityID node'
'Set Customer = DOM.DocumentElement.getElementsByTagName("CustomerId")(0)'

Dim itm As IXMLDOMNode

'# Instead of getting the first item like we did before, we can iterate the collection'
' of nodes with the entityID tag like so:'
For Each Customer In DOM.DocumentElement.getElementsByTagName("entityId")
   'Since Item is Entity nextSibling, and Entity is parent of entityId,'
   ' we can iterate the collection if its childNodes like this:'
    For Each itm In Customer.ParentNode.NextSibling.ChildNodes
        If itm.HasChildNodes Then
            '# Insert this node before the first child node of Item'
            itm.InsertBefore Customer.CloneNode(True), itm.FirstChild
        Else
            '# Append this node to the Item'
            itm.appendChild Customer.CloneNode(True)
        End If
    Next
Next

'##### This function call is no longer needed
'AppendCustomer DOM, "Transaction", Customer'

如:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Results>
        <Reference>{REFERENCE-HERE}</Reference>
        <FillerTags>Filler</FillerTags>
        <entity>
            <entityName>ABC</entityName>
            <entityId>012345</entityId>
        </entity>
        <Items>
            <Item>
                <entityId>012345</entityId>
                <FillerTagsAgain>Filler1</FillerTagsAgain>
                <FillerTagsAgain>Filler1</FillerTagsAgain>
                <FillerTagsAgain>Filler1</FillerTagsAgain>
            </Item>
            <AnotherItem>
                <entityId>012345</entityId>
                <FillerTagsAgain>Filler2</FillerTagsAgain>
                <FillerTagsAgain>Filler2</FillerTagsAgain>
                <FillerTagsAgain>Filler2</FillerTagsAgain>
            </AnotherItem>
        </Items>
    </Results>
    <Results>
        <Reference>{REFERENCE-HERE}</Reference>
        <FillerTags>Filler</FillerTags>
        <entity>
            <entityName>DEF</entityName>
            <entityId>54321</entityId>
        </entity>
        <Items>
            <Item>
                <entityId>54321</entityId>
                <FillerTagsAgain>Filler1</FillerTagsAgain>
                <FillerTagsAgain>Filler1</FillerTagsAgain>
                <FillerTagsAgain>Filler1</FillerTagsAgain>
            </Item>
            <AnotherItem>
                <entityId>54321</entityId>
                <FillerTagsAgain>Filler2</FillerTagsAgain>
                <FillerTagsAgain>Filler2</FillerTagsAgain>
                <FillerTagsAgain>Filler2</FillerTagsAgain>
            </AnotherItem>
        </Items>
    </Results>
</root>

这篇关于XML文件输出仅显示字节顺序标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆