从XML(经典ASP)获取多个值

时间:2015-04-09 11:46:54

标签: asp-classic xml-parsing

我有一个包含大量数据的XML文件,我希望获得一些值,以便在经典ASP中进一步处理。

我的XML文件看起来像这样;

<result>
<items>
    <client>
        <clientid>12345</clientid>
        <name>Acme Inc</name>
        <site>
            <siteid>98765</siteid>
            <name>Acme Site</name>
            <workstations>
                <workstation>
                    <id>12345</id>
                    <name>LAPTOP1</name>
                    <failed_checks>
                        <check>
                            <checkid>9876543</checkid>
                            <check_type>687</check_type>
                            <description>Smart Error</description>
                            <startdate>2015-04-09</startdate>
                            <starttime>12:01:00</starttime>
                            <formatted_output>Smart Error</formatted_output>
                        </check>
                    </failed_checks>
                </workstation>
            </workstations>
        </site>
    </client>
    <client>
        <clientid>67543</clientid>
        <name>Contoso Ltd</name>
        <site>
            <siteid>98732</siteid>
            <name>Contoso Site A</name>
            <servers>
                <server>
                    <id>789999</id>
                    <name>SERVER1</name>
                    <failed_checks>
                        <check>
                            <checkid>76543555</checkid>
                            <check_type>2918</check_type>
                            <description>Disk Space Error - C:</description>
                            <startdate>2015-04-09</startdate>
                            <starttime>12:01:00</starttime>
                            <formatted_output>Total: 136.70GB, Free: 0.57GB</formatted_output>
                        </check>
                    </failed_checks>
                </server>
            </servers>
        </site>
    </client>       
</items>

我的所有尝试都没有完全满足我的需求。 我每<client>获得一个值没有问题。我可以检索<client><name>或者我可以毫不费力地获得<check><description>的价值。我的问题是,当我希望<client><name><workstation><name><server><name>以及<check><description><check><startdate>的值相关时。

所以换句话说我想得到这个输出; Acme Inc LAPTOP1智能错误2015-04-09 Contoso Ltd SERVER1磁盘空间错误 - C:2015-04-09

我得到的最好结果是使用此代码; (它正常工作,但显示不正确 - <check><description><client><name>不匹配) 所以我的输出现在更像这样; Acme Inc SERVER1磁盘空间错误 - C:2015-04-09 Contoso Ltd LAPTOP1智能错误2015-04-09

Set xmlDOM = Server.CreateObject("MSXML2.DOMDocument")
xmlDOM.async = False
xmlDOM.setProperty "ServerHTTPRequest", True
xmlDOM.Load("my xml file")

Set Root = xmlDOM.documentElement
Set NodeList = Root.getElementsByTagName("client")

For i = 0 to NodeList.length -1
  Set clientid = xmlDOM.getElementsByTagName("clientid")(i)
  Set name = xmlDOM.getElementsByTagName("name")(i)
  Set ckdesc = xmlDOM.getElementsByTagName("site/*/*/failed_checks/check/description")(i)
  Set ckdev = xmlDOM.getElementsByTagName("site/*/*/name")(i) 

  Response.Write clientid.text & " " & name.text & " " & ckdev.text & " " & ckdesc.text & "<br>"
Next

Set xmlDOM = Nothing
Set NodeList = Nothing

我已经对selectNodesselectSingleNode进行了一些尝试,只显示客户端名称或检查说明。我没有设法得到价值观。

4 个答案:

答案 0 :(得分:1)

像这样使用selectNodesselectSingleNode

Dim xmlDOM
Set xmlDOM = Server.CreateObject("MSXML2.DOMDocument")
xmlDOM.LoadXml(sXml)

Dim NodeList, i, clientid, name, ckdesc, ckdev

Set NodeList = xmlDom.selectNodes("/result/items/client")

For i = 0 to NodeList.length -1
  Set clientid = NodeList(i).selectSingleNode("./clientid")
  Set name = NodeList(i).selectSingleNode("./name")
  Set ckdesc = NodeList(i).selectSingleNode("./site/*/*/failed_checks/check/description")
  Set ckdev = NodeList(i).selectSingleNode("./site/*/*/name")

  Response.Write clientid.text & " " & name.text & " " & ckdev.text & " " & ckdesc.text & "<br>"
Next

Set xmlDOM = Nothing
Set NodeList = Nothing

此代码并不理想,因为在获取属性值clientid.text之前,您需要检查该对象是否存在(并非一无所获),以及更多错误检查。

答案 1 :(得分:1)

Slint,我无法完成所有工作,抱歉,但我认为这个算法可以帮助您解决问题:

Dim nodeListClient, nodeClient
Dim nodeListSite, nodeSite
Dim nodeListMachine, nodeMachine

' getting multiply <client> nodes
Set nodeListClient = xmlDom.selectNodes("/result/items/client")

' looping through collection
For Each nodeClient In nodeListClient

    ' getting multiply <site> nodes
    Set nodeListSite = nodeClient.selectNodes("./site")

    ' looping through collection    
    For Each nodeSite In nodeListSites

        ' getting multiply <workstation> or <server> nodes
        Set nodeListMachine = nodeSite.selectNodes("./*/*")

        ' looping through collection
        For Each nodeMachine In nodeListMachine
            ' there you will working with nodeMachine object
            ' nodeMachine contains <id>, <name> and other nodes
        Next
    Next

Next

我建议您学习XPath文档和示例,例如https://msdn.microsoft.com/en-us/library/ms256115(v=vs.110).aspx

答案 2 :(得分:0)

我正在为VMV答案添加答案,以便能够更轻松地显示我的代码和输出。

VMV,您建议的代码就像一个魅力!直到我看到你工作代码的输出,我才看到整件事。 现在的问题是每个<client>可以有多个<sites>,每个<site>可以有多个<workstations><servers>,当然还有多个<check>。< / p>

如何在每个(i)进行循环?

我尝试过以下代码:     设置NodeList = xmlDom.selectNodes(“/ result / items / client”)

For i = 0 to NodeList.length -1
  Set clientid = NodeList(i).selectSingleNode("./clientid")
  Set name = NodeList(i).selectSingleNode("./name")

    Set NodeList2 = xmlDom.selectNodes("/result/items/client/site/*/*")
    For j = 0 to NodeList2.length -1
    Set ckdev = NodeList2(j).selectSingleNode("./name")     
        If Not ckdev Is Nothing Then    
            strckdev = strckdev & ckdev.text & " "
        Else
            strckdev = strckdev & "<br>"
        End If              

            Set NodeList3 = xmlDom.selectNodes("/result/items/client/site/*/*/failed_checks/check")
            For k = 0 to NodeList3.length -1
            Set ckdesc = NodeList3(k).selectSingleNode("./description")
              If Not ckdesc Is Nothing Then
                strckdesc = strckdesc & ckdesc.text & "<br>"
              Else
                strckdesc = strckdesc & "<br>"
              End If 
            Next      
    Next   

Response.Write clientid.text & " " & name.text & " " & strckdev & " " & strckdesc & "<br>"
Next

现在我每<clientid> <site>获得一次<site>。不仅仅是<clientid>(i)的12345 Acme Inc LAPTOP1 SERVER1 Smart Error Disk Space Error - C: 67543 Contoso Ltd LAPTOP1 SERVER1 Smart Error Disk Space Error - C:

结果如下:

12345 Acme Inc 
      LAPTOP1 Smart Error 
      LAPTOP3 Some other error 
              Second error 

67543 Contoso Ltd
      SERVER1 Disk Space Error - C:
      Server7 Some other error

我更喜欢这个结果(如果单个或多个计算机出现单个或多个错误):

Set clientid = NodeList(i).selectSingleNode("./clientid")
Set name = NodeList(i).selectSingleNode("./name")
Set ckdev = NodeList(i).selectNodes("./site/*/*/name") 
 For Each device In ckdev
   If Not device Is Nothing Then    
    strckdev = strckdev & device & " "
   Else
    strckdev = strckdev & "<br>"
   End If 
 Next

所以我的问题是,我如何在循环中循环..?

在我的代码中有明显的错误,我设置NodeList2和Set NodeList3,因为它再次通过XML文件,这就是我输出错误的原因。

我也尝试过这样做(基于VMV代码);

{{1}}

答案 3 :(得分:0)

根据VMVs答案,这是我的工作代码。原始文本中的数据输出没有很好的演示文稿。

Set xmlDOM = Server.CreateObject("MSXML2.DOMDocument")
xmlDOM.async = False
xmlDOM.setProperty "ServerHTTPRequest", True
xmlDOM.Load("XMLfiletoload")

Dim nodeListClient, nodeClient
Dim nodeListSite, nodeSite
Dim nodeListMachine, nodeMachine
Dim nodeError, nodeErrorList

' getting multiply <client> nodes
Set nodeListClient = xmlDom.selectNodes("/result/items/client")

' looping through collection
For Each nodeClient In nodeListClient
  Set clientid = nodeClient.selectSingleNode("./clientid")
  Set name = nodeClient.selectSingleNode("./name")
    ' getting multiply <site> nodes
  strCLIENT = clientid.text & " " & name.text & "<br>"

    Set nodeListSite = nodeClient.selectNodes("./site")

    ' looping through collection    
    For Each nodeSite In nodeListSite
        Set cksite = nodeSite.selectSingleNode("./name")
        If Not cksite Is Nothing Then 
            strSITE = cksite.text & " "
        Else
            strSITE = " "
        End If

        ' getting multiply <workstation> or <server> nodes
        Set nodeListMachine = nodeSite.selectNodes("./*/*")

        ' looping through collection
        For Each nodeMachine In nodeListMachine
            ' there you will working with nodeMachine object
            ' nodeMachine contains <id>, <name> and other nodes

            Set ckdev = nodeMachine.selectSingleNode("./name")
            If Not ckdev Is Nothing Then 
                strONEDEVICE = ckdev.text & " "
            Else
                strONEDEVICE = ""
            End If  

            Set nodeErrorList = nodeMachine.selectNodes("./failed_checks/check")            
            ' looping through collection
            For Each nodeError In nodeErrorList
                    ' there you will working with nodeError object
                    ' nodeError contains <id>, <name> and other nodes

                Set ckdesc = nodeError.selectSingleNode("./description")
                If Not ckdesc Is Nothing Then 
                    strERROR = strERROR & ckdesc.text & "<br>"
                Else
                    strERROR = strERROR & "<br>"
                End If  

            Next
        strDEVICE = strDEVICE & strONEDEVICE & strERROR
        Next
        strSITE = strSITE & strDEVICE
    Next
              Response.Write strCLIENT & " " & strSITE & "<br>"
              strCLIENT = ""
              strSITE = ""
              strONEDEVICE = ""
              strDEVICE = ""
              strERROR = ""

Next