这是另一个关于如何获取属性值的问题。我知道使用Microsoft的MSXML2 SelectNodes和SelectSingleNode方法时存在限制,因为它们必须返回一个节点集。
我曾经以为在表达式末尾使用text()并没有返回一个节点集,但后来我发现了IXMLDOMText类型,它可以看作是IXMLDOMAttribute类型的子节点,让我想知道是不是真的可以使用XPath来挖掘属性的值。
IXMLDOMText是一个节点,而不是文字,因此(理论上)它可以参与节点集,即节点集可以包含一个IXMLDOMText。
这是一些实验性代码。它在Excel VBA中运行,您需要设置工具 - >参考
你可以在底部看到我的尝试注释了我的尝试。任何聪明的人都知道答案吗?
我希望能够在节点上调用.xml方法并获取属性的值,目前这样做会给出键值和值对,而不仅仅是值。
对版主而言,请不要将其视为副本,因为我认为我已经发现了一个新的角度。
以下SO文章都建议将Xpath包装在string()中,但这对MSXML2.SelectNodes不起作用,因为它必须返回一个节点集
Getting attribute using XPath
Extract value of attribute node via XPath
How to get attribute value from node using xpath?
Option Explicit
Sub Test()
'* Requires Tools->References-> Microsoft XML, v6.0
Dim doc As MSXML2.DOMDocument60
Set doc = New MSXML2.DOMDocument60
'* THE OBJECTIVE IS TO INVENT AN XPATH THAT RETRIEVES THE VALUE OF AN ATTRIBUTE USING SOMETHING LIKE /a/c/@id/text()
Dim s As String
s = _
"<a>" & _
"<b>1stbText" & _
"</b>" & _
"<b>2ndbText" & _
"</b>" & _
"<c id='5'>cText" & _
"</c>" & _
"</a>"
doc.LoadXML s
Debug.Assert doc.parseError = 0
TestB doc
TestA doc
TestC doc
TestCID doc
TestCIDText doc
End Sub
Sub TestB(ByVal doc As MSXML2.DOMDocument60)
Dim xmlBTextNodes As MSXML2.IXMLDOMNodeList
Set xmlBTextNodes = doc.SelectNodes("/a/b/text()")
Debug.Assert Not xmlBTextNodes Is Nothing
Debug.Assert xmlBTextNodes.Length = 2
Debug.Assert xmlBTextNodes(0).Text = "1stbText"
Debug.Assert xmlBTextNodes(1).Text = "2ndbText"
Debug.Assert TypeName(xmlBTextNodes(0)) = "IXMLDOMText"
Dim xmlCastToText As MSXML2.IXMLDOMText
Set xmlCastToText = xmlBTextNodes(0)
Debug.Assert xmlCastToText.xml = "1stbText"
Debug.Assert xmlCastToText.Text = "1stbText"
End Sub
Sub TestA(ByVal doc As MSXML2.DOMDocument60)
Dim xmlATextNodes As MSXML2.IXMLDOMNodeList
Set xmlATextNodes = doc.SelectNodes("/a/text()")
Debug.Assert Not xmlATextNodes Is Nothing
Debug.Assert xmlATextNodes.Length = 0 '* interesting
End Sub
Sub TestC(ByVal doc As MSXML2.DOMDocument60)
Dim xmlCTextNodes As MSXML2.IXMLDOMNodeList
Set xmlCTextNodes = doc.SelectNodes("/a/c/text()")
Debug.Assert Not xmlCTextNodes Is Nothing
Debug.Assert xmlCTextNodes.Length = 1
Debug.Assert xmlCTextNodes(0).xml = "cText"
Debug.Assert xmlCTextNodes(0).Text = "cText"
Dim xmlCastToText As MSXML2.IXMLDOMText
Set xmlCastToText = xmlCTextNodes(0)
Debug.Assert xmlCastToText.xml = "cText"
Debug.Assert xmlCastToText.Text = "cText"
End Sub
Sub TestCID(ByVal doc As MSXML2.DOMDocument60)
Dim xmlCIDNodes As MSXML2.IXMLDOMNodeList
Set xmlCIDNodes = doc.SelectNodes("/a/c/@id")
Debug.Assert Not xmlCIDNodes Is Nothing
Debug.Assert xmlCIDNodes.Length = 1
Debug.Assert xmlCIDNodes(0).xml = "id=""5"""
Debug.Assert xmlCIDNodes(0).Text = "5"
Debug.Assert TypeName(xmlCIDNodes(0)) = "IXMLDOMAttribute"
Debug.Assert xmlCIDNodes(0).ChildNodes.Length = 1
Dim xmlCastToText As MSXML2.IXMLDOMText
Set xmlCastToText = xmlCIDNodes(0).ChildNodes(0)
Debug.Assert xmlCastToText.xml = "5"
Debug.Assert xmlCastToText.Text = "5"
Debug.Assert xmlCastToText.ChildNodes.Length = 0
End Sub
Sub t2()
'* a convenient entry so I can press F5 and run in the same vicinity as Sub TestCIDText()
Test
End Sub
Sub TestCIDText(ByVal doc As MSXML2.DOMDocument60)
Dim xmlCIDTextNodes As MSXML2.IXMLDOMNodeList
'*** crucial XPath where I'd like to retrieve the text of an attribute
'Set xmlCIDTextNodes = doc.SelectNodes("/a/c/@id/text") '* doesn't work, returns 0 nodes
'Set xmlCIDTextNodes = doc.SelectNodes("/a/c/@id/text()") '* doesn't work, returns 0 nodes
'Set xmlCIDTextNodes = doc.SelectNodes("string(/a/c/@id)") '* doesn't work, throws "Expression must evaluate to a node-set. -->string(/a/c/@id)<--"
Debug.Assert Not xmlCIDTextNodes Is Nothing
Debug.Assert xmlCIDTextNodes.Length = 1 '<========stops here because of XPath not working
Debug.Assert xmlCIDTextNodes(0).xml = "5" '<== we can predict these results from the tail of Sub TestCID
Debug.Assert xmlCIDTextNodes(0).Text = "5"
Debug.Assert xmlCIDTextNodes(0).ChildNodes.Length = 0
End Sub
答案 0 :(得分:0)
Sub Test()
'* Requires Tools->References-> Microsoft XML, v6.0
Dim doc As MSXML2.DOMDocument60
Dim nl As MSXML2.IXMLDOMNodeList
Dim s As String, n As MSXML2.IXMLDOMNode
Dim v
Set doc = New MSXML2.DOMDocument60
s = "<a>" & _
"<b>1stbText" & _
"</b>" & _
"<b>2ndbText" & _
"</b>" & _
"<c id='5'>cText" & _
"</c>" & _
"</a>"
doc.LoadXML s
'if possibly multiple matches...
Set nl = doc.SelectNodes("/a/c/@id")
For Each n In nl
Debug.Print n.NodeValue ' >> "5"
Next n
'if expecting just one match...
Set n = doc.SelectSingleNode("/a/c/@id")
If Not n Is Nothing Then Debug.Print n.NodeValue '>> "5"
'or?
Debug.Print doc.SelectSingleNode("/a/c/@id").Text
End Sub