네임 스페이스가있는 XPath 선택 노드
.vbproj이며 다음과 같습니다.
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>15a7ee82-9020-4fda-a7fb-85a61664692d</ProjectGuid>
내가 원하는 것은 ProjectGuid이지만 네임 스페이스가 있으면 작동하지 않습니다 ...
Dim xmlDoc As New XmlDocument()
Dim filePath As String = Path.Combine(mDirectory, name + "\" + name + ".vbproj")
xmlDoc.Load(filePath)
Dim value As Object = xmlDoc.SelectNodes("/Project/PropertyGroup/ProjectGuid")
이 문제를 해결하려면 어떻게해야합니까?
이와 같은 작업을 수행하는 가장 좋은 방법 (IMHO)은 네임 스페이스 관리자를 만드는 것입니다. 이는 SelectNodes를 호출하여 어떤 네임 스페이스 URL이 어떤 접두사에 연결되어 있는지 나타내는 데 사용할 수 있습니다. 일반적으로 다음과 같은 적절한 인스턴스를 반환하는 정적 속성을 설정합니다 (C #이므로 번역해야 함).
private static XmlNamespaceManager _nsMgr;
public static XmlNamespaceManager NsMgr
{
get
{
if (_nsMgr == null)
{
_nsMgr = new XmlNamespaceManager(new NameTable());
_nsMgr.AddNamespace("msb", "http://schemas.microsoft.com/developer/msbuild/2003");
}
return _nsMgr;
}
}
여기에는 하나의 네임 스페이스 만 포함되지만 여러 개를 가질 수 있습니다. 그런 다음 다음과 같이 문서에서 선택할 수 있습니다.
Dim value As Object = xmlDoc.SelectNodes("/msb:Project/msb:PropertyGroup/msb:ProjectGuid", NsMgr)
모든 요소는 지정된 네임 스페이스에 있습니다.
아마도
Bartek의
* 네임 스페이스 솔루션을 사용하는 경향이
있지만 일반적인 xpath 솔루션은 다음과 같습니다.
//*[local-name()='ProjectGuid']
** Bartek의 답변이 사라졌기 때문에 Teun의 답변을 추천합니다 (실제로 더 철저 함) *
어느 쪽이든 당신은 공간에 독립적 XPath 식 작업 (하지의 어색함과 거짓 긍정적 인 일치의 가능성 권장 - <msb:ProjectGuid>
그리고 <foo:ProjectGuid>
이 표현에 대해 동일합니다)
// * [local-name () = 'ProjectGuid']
또는 옳은 일을하고를 사용 XmlNamespaceManager
하여 네임 스페이스 URI를 등록하면 XPath에 네임 스페이스 접두사를 포함 할 수 있습니다.
Dim xmlDoc As New XmlDocument()
xmlDoc.Load(Path.Combine(mDirectory, name, name + ".vbproj"))
Dim nsmgr As New XmlNamespaceManager(xmlDoc.NameTable)
nsmgr.AddNamespace("msb", "http://schemas.microsoft.com/developer/msbuild/2003")
Dim xpath As String = "/msb:Project/msb:PropertyGroup/msb:ProjectGuid"
Dim value As Object = xmlDoc.SelectNodes(xpath, nsmgr)
쿼리가 작동하도록하려면이 XML 네임 스페이스를 등록하고 접두사와 연결하기 만하면됩니다. 노드를 선택할 때 네임 스페이스 관리자를 두 번째 매개 변수로 만들고 전달합니다.
Dim ns As New XmlNamespaceManager ( xmlDoc.NameTable )
ns.AddNamespace ( "msbuild", "http://schemas.microsoft.com/developer/msbuild/2003" )
Dim value As Object = xmlDoc.SelectNodes("/msbuild:Project/msbuild:PropertyGroup/msbuild:ProjectGuid", ns)
One way is to use extensions + NameSpaceManager.
Code is in VB but is realy easy to translate to C#.
Imports System.Xml
Imports System.Runtime.CompilerServices
Public Module Extensions_XmlHelper
'XmlDocument Extension for SelectSingleNode
<Extension()>
Public Function _SelectSingleNode(ByVal XmlDoc As XmlDocument, xpath As String) As XmlNode
If XmlDoc Is Nothing Then Return Nothing
Dim nsMgr As XmlNamespaceManager = GetDefaultXmlNamespaceManager(XmlDoc, "x")
Return XmlDoc.SelectSingleNode(GetNewXPath(xpath, "x"), nsMgr)
End Function
'XmlDocument Extension for SelectNodes
<Extension()>
Public Function _SelectNodes(ByVal XmlDoc As XmlDocument, xpath As String) As XmlNodeList
If XmlDoc Is Nothing Then Return Nothing
Dim nsMgr As XmlNamespaceManager = GetDefaultXmlNamespaceManager(XmlDoc, "x")
Return XmlDoc.SelectNodes(GetNewXPath(xpath, "x"), nsMgr)
End Function
Private Function GetDefaultXmlNamespaceManager(ByVal XmlDoc As XmlDocument, DefaultNamespacePrefix As String) As XmlNamespaceManager
Dim nsMgr As New XmlNamespaceManager(XmlDoc.NameTable)
nsMgr.AddNamespace(DefaultNamespacePrefix, XmlDoc.DocumentElement.NamespaceURI)
Return nsMgr
End Function
Private Function GetNewXPath(xpath As String, DefaultNamespacePrefix As String) As String
'Methode 1: The easy way
Return xpath.Replace("/", "/" + DefaultNamespacePrefix + ":")
''Methode 2: Does not change the nodes with existing namespace prefix
'Dim Nodes() As String = xpath.Split("/"c)
'For i As Integer = 0 To Nodes.Length - 1
' 'If xpath starts with "/", don't add DefaultNamespacePrefix to the first empty node (before "/")
' If String.IsNullOrEmpty(Nodes(i)) Then Continue For
' 'Ignore existing namespaces prefixes
' If Nodes(i).Contains(":"c) Then Continue For
' 'Add DefaultNamespacePrefix
' Nodes(i) = DefaultNamespacePrefix + ":" + Nodes(i)
'Next
''Create and return then new xpath
'Return String.Join("/", Nodes)
End Function
End Module
And to use it:
Imports Extensions_XmlHelper
......
Dim FileXMLTextReader As New XmlTextReader(".....")
FileXMLTextReader.WhitespaceHandling = WhitespaceHandling.None
Dim xmlDoc As XmlDocument = xmlDoc.Load(FileXMLTextReader)
FileXMLTextReader.Close()
......
Dim MyNode As XmlNode = xmlDoc._SelectSingleNode("/Document/FirstLevelNode/SecondLevelNode")
Dim MyNode As XmlNodeList = xmlDoc._SelectNodes("/Document/FirstLevelNode/SecondLevelNode")
......
Why not use the // to ignore the namespace:
Dim value As Object = xmlDoc.SelectNodes("//ProjectGuid")
// acts as wild card to follow through everything between the root and the next node name specified(i.e ProjectGuid)
참고URL : https://stackoverflow.com/questions/536441/xpath-select-node-with-namespace
'Nice programing' 카테고리의 다른 글
MongoDb : $ push / $ addtoset의 차이점 (0) | 2020.11.20 |
---|---|
환경 이름 (IHostingEnvironment.EnvironmentName)을 설정하는 방법은 무엇입니까? (0) | 2020.11.20 |
클래스 매핑 오류 : 'T'는 매개 변수가없는 공용 생성자가있는 비추 상 유형이어야합니다. (0) | 2020.11.20 |
MySQL의 필드 값과 함께 LIKE % .. % 사용 (0) | 2020.11.20 |
Java에서 두 문자열을 비교하고 알파벳순으로 다른 문자열보다 작은 문자열을 어떻게 정의 할 수 있습니까? (0) | 2020.11.20 |