2011-10-14 61 views
7

我在MATLAB實現的一個非常愚蠢的XPath過濾器:xmlns聲明打破了我的XPath過濾器

% Construct the DOM. 
docNode = xmlread('C:\Users\MATLAB\test.gpx'); 

% get the xpath mechanism into the workspace 
import javax.xml.xpath.* 
factory = XPathFactory.newInstance; 
xpath = factory.newXPath; 

% compile and evaluate the XPath Expression 
expression = xpath.compile('gpx/AddressBook/Entry/PhoneNumber'); 
phoneNumberNode = expression.evaluate(docNode, XPathConstants.NODE); 
phoneNumber = phoneNumberNode.getTextContent 

有了這個XML(特別是有.GPX文件),它的工作原理:

<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?> 
<gpx version='1.1' creator='TTTracklog V.1.13'> 
    <AddressBook> 
     <Entry> 
      <Name>Friendly J. Mathworker</Name> 
      <PhoneNumber>(508) 647-7000</PhoneNumber> 
      <Address hasZip="no" type="work">3 Apple Hill Dr, Natick MA</Address> 
     </Entry> 
    </AddressBook> 
</gpx> 

和文字( 508)647-7000被返回。 簡單地增加xmlns屬性來GPX節點以這樣的方式

<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?> 
<gpx version='1.1' creator='TTTracklog V.1.13' xmlns='http://www.topografix.com/GPX/1/1'> 
    <AddressBook> 
     <Entry> 
      <Name>Friendly J. Mathworker</Name> 
      <PhoneNumber>(508) 647-7000</PhoneNumber> 
      <Address hasZip="no" type="work">3 Apple Hill Dr, Natick MA</Address> 
     </Entry> 
    </AddressBook> 
</gpx> 

給了我的錯誤,和MATLAB報告:

???嘗試去引用非結構數組字段。

在12 phoneNumber的= phoneNumberNode.getTextContent

爲什麼在==>測試錯誤?我怎樣才能避免這個錯誤?

+2

我不知道MATLAB,但從XML的角度來看,您現在已將gpx(etc.)元素放置在http://www.topografix.com/GPX/1/1名稱空間中,XPath正在全局名稱空間中查找它。您需要以某種方式使MatLab知道名稱空間,然後限定XPath表達式中的gpx元素。 – Dabbler

+0

好問題,+1。如果你沒有Matlab中的機制來註冊一個命名空間,你可以使用這樣的表達式:'* [name()='gpx'] /* [name()='AddressBook'] /* [name()='Entry'] /* [name()='PhoneNumber']' –

+1

@_Mariano:我的回答有用嗎? –

回答

0

上面的Dabbler的評論是正確的。由於您已將默認名稱空間添加到XML文檔中,因此還必須更改XPath表達式以搜索新默認名稱空間中的節點。

XPath表達式中的非限定名稱(如AddressBook)位於null XML名稱空間中,而不是文檔的默認XML名稱空間。

所以你想以某種方式註冊你的新命名空間與你的xpath對象。像:

{"foo": "http://www.topografix.com/GPX/1/1"} 

,然後改變你的XPath表達式:

foo:gpx/foo:AddressBook/foo:Entry/foo:PhoneNumber 

對於如何與javax.xml.xpath API這裏做這個文檔:

http://www.ibm.com/developerworks/library/x-javaxpathapi/index.html#N1022D

然而,我我不確定這究竟是如何轉化爲Matlab的。

+1

你是對的!我應該聲明一個路徑名稱。我已經在matlab論壇上發佈了這個問題。我會盡快報告,他們會回答我。 –

+0

應該完全翻譯,因爲它使用的是Java類。 – Nzbuu

+0

對於特定於MATLAB的實現,我在此博客評論中發佈了一個示例:http://blogs.mathworks.com/desktop/2010/11/01/xml-and-matlab-navigating-a-tree/#comment- 8353您仍然需要爲NamespaceContext使用java類 –

6

如果你不能與相關的前綴寄存器的默認命名空間,使用:

*[name()= 'gpx'] 
    /*[name()='AddressBook'] 
     /*[name()='Entry'] 
      /*[name() = 'PhoneNumber'] 

代替:

gpx/AddressBook/Entry/PhoneNumber 

下面是一個完整的,基於XSLT的,驗證

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:copy-of select= 
    "*[name()= 'gpx'] 
    /*[name()='AddressBook'] 
     /*[name()='Entry'] 
      /*[name() = 'PhoneNumber'] 
    "/> 
</xsl:template> 
</xsl:stylesheet> 

當這種轉變是在所提供的XML文檔應用:

<?xml version='1.0' encoding='ISO-8859-1' standalone='yes' ?> 
<gpx version='1.1' creator='TTTracklog V.1.13' xmlns='http://www.topografix.com/GPX/1/1'> 
    <AddressBook> 
     <Entry> 
      <Name>Friendly J. Mathworker</Name> 
      <PhoneNumber>(508) 647-7000</PhoneNumber> 
      <Address hasZip="no" type="work">3 Apple Hill Dr, Natick MA</Address> 
     </Entry> 
    </AddressBook> 
</gpx> 

想要的元素被選中並複製到輸出

<PhoneNumber xmlns="http://www.topografix.com/GPX/1/1">(508) 647-7000</PhoneNumber> 
+0

代碼: 'e1 = xPath.compile('* [name()=「gpx」]/* [name()=「trk」]'); s = e1.evaluate(gpx,XPathConstants.NODESET); sNumber = s.getLength;' 編譯並返回我的確切值。雖然 'e2 = xPath.compile('* [name()=「gpx」]/* [name()=「trk [1]」]/* [name()=「trkseg」]'); s = e2.evaluate(gpx,XPathConstants.NODESET); sNumber = s.getLength;' 總是返回0值。爲什麼?這是第二個表達式的'[1]'嗎? –

+0

@Mariano:當然。名稱只能包含字母數字字符(以alpha開頭) - 不是'[]'。你真的想要:'* [name()='trk'] [1]' –

+0

你是男人!最後一件事:屬性呢?例如:如何用這個符號獲取經度和緯度? 我有類似'gpx/trk [1]/trkseg [1]/trkpt [2]/@ lat'的東西,我需要使用name()重寫。 –