2011-10-14 31 views
7

tôi đã nhận ra một bộ lọc xPath thực sự ngu ngốc trong Matlab:khai xmlns đã phá vỡ lọc xPath tôi

% 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 

Với XML này (cụ thể là một file .gpx) nó hoạt động:

<?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> 

và văn bản (508) 647-7000 được trả lại. xmlns Đơn giản chỉ cần thêm thuộc tính cho nút GPX theo cách này:

<?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> 

đã cho tôi lỗi, và báo cáo matlab:

??? Cố gắng tham chiếu trường của mảng không cấu trúc.

Lỗi trong ==> kiểm tra tại 12 PhoneNumber = phoneNumberNode.getTextContent

Tại sao? Làm thế nào tôi có thể tránh được lỗi đó?

+2

Tôi không biết Matlab, nhưng từ một quan điểm XML, bây giờ bạn đã đặt phần tử gpx (v.v.) của bạn trong không gian tên http://www.topografix.com/GPX/1/1 và XPath đang tìm kiếm nó trong không gian tên chung. Bạn cần bằng cách nào đó làm cho không gian tên được biết đến với MatLab và sau đó đủ điều kiện phần tử gpx trong biểu thức XPath. – Dabbler

+0

Câu hỏi hay, +1. Trong trường hợp bạn không có cơ chế trong Matlab để đăng ký một không gian tên, bạn có thể sử dụng một biểu thức như sau: '* [name() = 'gpx'] /* [name() = 'AddressBook'] /* [name() = 'Entry'] /* [name() = 'PhoneNumber'] ' –

+1

@_Mariano: Câu trả lời của tôi có hữu ích không? –

Trả lời

0

Nhận xét của Dabbler ở trên là chính xác. Vì bạn đã thêm một không gian tên mặc định vào tài liệu XML của mình, bạn cũng phải thay đổi biểu thức XPath của bạn để tìm kiếm các nút trong không gian tên mặc định mới của bạn.

Tên không đủ tiêu chuẩn trong biểu thức XPath (như AddressBook) nằm trong không gian tên null XML, không phải là không gian tên XML mặc định của tài liệu của bạn.

Vì vậy, bạn muốn bằng cách nào đó đăng ký không gian tên mới của mình với đối tượng xpath. Giống như:

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

và sau đó thay đổi biểu thức XPath của bạn để:

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

Có tài liệu về cách để làm điều này với javax.xml.xpath API ở đây:

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

Tuy nhiên, tôi 'không chắc chắn làm thế nào điều này dịch Matlab, chính xác.

+1

Bạn nói đúng! Tôi nên khai báo một tên đường dẫn. Tôi đã đăng câu hỏi trên diễn đàn MATLAB. Tôi sẽ báo cáo ngay khi họ trả lời tôi. –

+0

Cần dịch chính xác, vì nó đang sử dụng các lớp Java. – Nzbuu

+0

Để thực hiện MATLAB cụ thể, tôi đã đăng một ví dụ trong nhận xét blog này: http://blogs.mathworks.com/desktop/2010/11/01/xml-and-matlab-navigating-a-tree/#comment- 8353 Bạn vẫn cần sử dụng lớp java cho NamespaceContext –

6

Trong trường hợp bạn không thể đăng ký tên miền không gian mặc định với một tiền tố liên quan, sử dụng:

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

thay vì:

gpx/AddressBook/Entry/PhoneNumber 

Dưới đây là một hoàn chỉnh, XSLT-based, xác minh:

<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> 

khi chuyển đổi này được áp dụng trên các tài liệu XML cung cấp:

<?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> 

yếu tố truy nã đã được chọn và sao chép vào đầu ra:

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

Mã: 'e1 = xPath.compile ('* [tên() =" gpx "]/* [tên() =" trk "]'); s = e1.đánh giá (gpx, XPathConstants.NODESET); sNumber = s.getLength; ' biên dịch và trả lại giá trị chính xác cho tôi. Trong khi 'e2 = xPath.compile ('* [tên() =" gpx "]/* [tên() =" trk [1] "]/* [tên() =" trkseg "]'); s = e2.evaluate (gpx, XPathConstants.NODESET); sNumber = s.getLength; ' luôn trả về 0 giá trị. Tại sao? Đây có phải là '[1]' của biểu thức thứ hai không? –

+0

@Mariano: Tất nhiên. Tên chỉ có thể chứa các ký tự chữ và số (bắt đầu bằng alpha) - không phải là '[]'. Bạn thực sự muốn: '* [name() = 'trk'] [1]' –

+0

Bạn là người đàn ông! Điều cuối cùng: những gì về thuộc tính? Ví dụ: làm thế nào tôi có thể nhận được vĩ độ và kinh độ với ký hiệu này? Tôi có một cái gì đó như 'gpx/trk [1]/trkseg [1]/trkpt [2]/@ lat' mà tôi cần viết lại bằng tên(). –

Các vấn đề liên quan