当内容为空时,无法在XML中拆分节点的内容

时间:2011-10-19 13:03:00

标签: xml vbscript asp-classic msxml

提供以下XML我试图通过|将“额外”节点的内容分成四个部分分隔符并将响应中的四个部分作为chdspt(0),chdspt(1),chdspt(2)和chdspt(3)返回。我似乎遇到的问题是,如果加载的XML缺少“额外”节点内的任何内容,那么整个脚本会因500错误而失败。

<Export>
    <SAVED_EXPORT>
        <id>00-6189</id>
        <title>00-6189 Start Mech Switch</title>
        <price>5.46 USD</price>
        <extra>Male|Adult|Black|medium</extra>
    </SAVED_EXPORT>
    <SAVED_EXPORT>
        <id>00-6190</id>
        <title>00-6190 Start Mech Switch</title>
        <price>5.46 USD</price>
        <extra></extra>
    </SAVED_EXPORT>
</Export>

请注意,我从上面的XML中删除了很多兄弟节点,因为它发布的内容太多了,对于手头的问题来说应该是不必要的。

Dim xData,xNewDoc,xmldataout,xmldataout2,title,description,link,gpc,chd,chdspt

url = "http://thesite.com/v/myxml.xml"
Set xData = Server.CreateObject("Microsoft.XMLHTTP")
xData.Open "get", url, False
xData.Send
Set xNewDoc = xData.responseXML 'ResponseXml returns DOMDocument object

For Each x In xNewDoc.documentElement.selectNodes(".//SAVED_EXPORT")

    Dim productid: Set productid = x.selectSingleNode("id")
    Dim pt: Set pt = x.selectSingleNode("title")
    Dim pds: Set pds = x.selectSingleNode("striphtml-description")
    Dim pl: Set pl = x.selectSingleNode("link")
    Dim pe: Set pe = x.selectSingleNode("product_type")
    Dim pri: Set pri = x.selectSingleNode("price")
    Dim psp: Set psp = x.selectSingleNode("sale_price")
    Dim pbr: Set pbr = x.selectSingleNode("brand")
    Dim pcn: Set pcn = x.selectSingleNode("condition")
    Dim pex: Set pex = x.selectSingleNode("expiration_date")
    Dim pwe: Set pwe = x.selectSingleNode("weight")
    Dim ppn: Set ppn = x.selectSingleNode("id")
    Dim pil: Set pil = x.selectSingleNode("image_link")
    Dim pav: Set pav = x.selectSingleNode("availability")
    Dim ppi: Set ppi = x.selectSingleNode("upc")
    Dim pch: Set pch = x.selectSingleNode("extra")

    title=Replace(pt.text,"&","&amp;")
    title=Replace(title,"<","&lt;")
    title=Replace(title,">","&gt;")

    description=Replace(pds.text,"&","&amp;")
    description=Replace(description,"<","&lt;")
    description=Replace(description,">","&gt;")

    link=Replace(pl.text,"&","&amp;")
    link=Replace(link,"<","&lt;")
    link=Replace(link,">","&gt;")

    gpc=Replace(pri.text,"&","&amp;")
    gpc=Replace(gpc,"<","&lt;")
    gpc=Replace(gpc,">","&gt;")

    chd = pch.text
    chdspt = split(chd, "|")    


xmldataout= "<item><g:id>" & productid.text & "</g:id>" & "<title>" & title & "</title>"
& "<description>" & description & "</description>" & "<link>" & link & "</link>"
& "<g:google_product_category>" & gpc & "</g:google_product_category>" & "<g:price>" & pri.text & "</g:price>" & "<g:sale_price>" & psp.text & "</g:sale_price>"
& "<g:brand>" & pbr.text & "</g:brand>" & "<g:condition>" & pcn.text & "</g:condition>"
& "<g:expiration_date>" & pex.text & "</g:expiration_date>" & "<g:shipping_weight>" & pwe.text & "</g:shipping_weight>" & "<g:mpn>" & ppn.text & "</g:mpn>"
& "<g:image_link>" & pil.text & "</g:image_link>" & "<g:availability>" & pav.text & "</g:availability>" & "<g:gtin>" & ppi.text & "</g:gtin>"
& "<g:gender>" & chdspt(0) &  "</g:gender>" & "<g:age_group>" & chdspt(1) & "</g:age_group>" & "<g:color>" & chdspt(2) & "</g:color>"
& "<g:size>" & chdspt(3) & "</g:size>  </item>" 

xmldataout2=xmldataout2+xmldataout
Next


Response.ContentType = "text/xml"
Response.Write("<?xml version='1.0' encoding='UTF-8'?><rss version='2.0' xmlns:g='http://base.google.com/ns/1.0'><channel><title>store</title><link>http://www.thesite.com</link><description>This is a sample feed</description>" & xmldataout2 & "</channel></rss>")

Set xNewDoc = Nothing
Set xData = Nothing

2 个答案:

答案 0 :(得分:1)

这是一个全新的代码版本,使用“最佳实践”(即没有手动字符转义,不使用字符串构建XML,而是使用DOM代替,使用当前COM对象(Microsoft.XMLHTTP已过时)

请注意,NewElem()GetText()是代码末尾的便捷功能。

  • NewElem()创建一个带或不带命名空间的新元素,并为其添加文本值
  • GetText()在上下文(文档或节点)中搜索XPath表达式,并返回找到的第一个元素的文本值,或""(即更智能的.selectSingleNode()

ASP代码:

Option Explicit

Const NODE_ELEMENT = 1

Dim Namespaces, XmlHttpReq, InputDoc, OutputDoc, Channel, x, NewItem
Dim url, StubFeed, v, vGender, vAgeGroup, vColor, vSize

url = "http://thesite.com/v/myxml.xml"
StubFeed = "<rss version='2.0' xmlns:g='http://base.google.com/ns/1.0'><channel><title>store</title><link>http://www.thesite.com</link><description>This is a sample feed</description></channel></rss>" 

' prepare a dictitionary of namespace prefixes and respective URIs
Set Namespaces = Server.CreateObject("Scripting.Dictionary")
Namespaces.Add "g", "http://base.google.com/ns/1.0"

Set OutputDoc  = Server.CreateObject("MSXML2.DOMDocument.4.0")
Set XmlHttpReq = Server.CreateObject("MSXML2.XMLHTTP.4.0")

' retrieve the source document
' TODO: Error handling in case the HTTP request fails!
XmlHttpReq.Open "GET", url, False
XmlHttpReq.Send
Set InputDoc = XmlHttpReq.responseXML

' the stub of the output is loaded from string
OutputDoc.loadXML StubFeed

' all new items are appended to this element
Set Channel = OutputDoc.selectSingleNode("/rss/channel")

For Each x In InputDoc.selectNodes("//SAVED_EXPORT")
  Set NewItem = OutputDoc.createElement("item")
  With NewItem
    .appendChild NewElem("g:id",                      GetText(x, "id"))
    .appendChild NewElem("title",                     GetText(x, "title"))
    .appendChild NewElem("description",               GetText(x, "striphtml-description"))
    .appendChild NewElem("link",                      GetText(x, "link"))
    .appendChild NewElem("g:google_product_category", GetText(x, "product_type"))
    .appendChild NewElem("g:price",                   GetText(x, "price"))
    .appendChild NewElem("g:sale_price",              GetText(x, "sale_price"))
    .appendChild NewElem("g:brand",                   GetText(x, "brand"))
    .appendChild NewElem("g:condition",               GetText(x, "condition"))
    .appendChild NewElem("g:expiration_date",         GetText(x, "expiration_date"))
    .appendChild NewElem("g:shipping_weight",         GetText(x, "weight"))
    .appendChild NewElem("g:mpn",                     GetText(x, "id"))
    .appendChild NewElem("g:image_link",              GetText(x, "image_link"))
    .appendChild NewElem("g:availability",            GetText(x, "availability"))
    .appendChild NewElem("g:gtin",                    GetText(x, "upc"))

    v = Split(Trim( GetText(x, "extra[normalize-space() != '']") ), "|")
    If UBound(v) = 3 Then
      vGender = v(0) : vAgeGroup = v(1) : vColor = v(2) : vSize = v(3)
    Else
      vGender = ""   : vAgeGroup = ""   : vColor = ""   : vSize = ""
    End If

    .appendChild NewElem("g:gender",    vGender)
    .appendChild NewElem("g:age_group", vAgeGroup)
    .appendChild NewElem("g:color",     vColor)
    .appendChild NewElem("g:size",      vSize)
  End With

  Channel.appendChild NewItem
Next

' send the feed (saving the document to the Response object does this)
Response.ContentType = "text/xml; charset=UTF-8"
OutputDoc.save Response

' --- HELPER FUNCTIONS ------------------------------------------------------
Function NewElem(name, text)
  Dim namespaceURI
  If InStr(name, ":") Then
    namespaceURI = Namespaces( Split(name, ":")(0) )
    Set NewElem = OutputDoc.createNode(NODE_ELEMENT, name, namespaceURI)
  Else
    Set NewElem = OutputDoc.createElement(name)
  End If

  If text <> "" Then NewElem.text = text
End Function

Function GetText(context, xPath)
  Dim node
  Set node = context.selectSingleNode(xPath)
  If node Is Nothing Then
    GetText = ""
  Else
    GetText = node.text
  End If
End Function

考虑使用更合适的application/rss+xml内容类型而不是text/xml

答案 1 :(得分:0)

注意到@TomaLak在上面的这行代码中遗漏了<?xml version='1.0' ?>

StubFeed = "<rss version='2.0' xmlns:g='http://base.google.com/ns/1.0'><channel><title>store</title><link>http://www.thesite.com</link><description>This is a sample feed</description></channel></rss>"