2011-10-14 10 views
7

zdałem sobie sprawę naprawdę głupiego filtr XPath w Matlab:deklaracja xmlns złamałam filtr 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 

Z tego XML (konkretnie .gpx pliku) to działa:

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

i tekstowej (508) Zwraca 647-7000. prostu dodając atrybut xmlns do węzła gpx w ten sposób:

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

dał mi błąd i raport Matlab:

??? Próba odwołania do pola tablicy non-structure.

Błąd w ==> badania w 12 PhoneNumber = phoneNumberNode.getTextContent

Dlaczego? Jak mogę uniknąć tego błędu?

+2

nie wiem, Matlab, ale z punktu widzenia XML, umieściłeś teraz element gpx (etc.) w przestrzeni nazw http://www.topografix.com/GPX/1/1, a XPath szuka jej w globalnym obszarze nazw. Musisz jakoś udostępnić obszar nazw MatLab, a następnie zakwalifikować element gpx w wyrażeniu XPath. – Dabbler

+0

Dobre pytanie, +1. Jeśli nie masz mechanizmów w Matlab, aby zarejestrować obszar nazw, możesz użyć takiego wyrażenia: '* [name() = 'gpx'] /* [name() = 'AddressBook'] /* [name() = 'Entry'] /* [name() = 'PhoneNumber'] ' –

+1

@_Mariano: Czy moja odpowiedź była przydatna? –

Odpowiedz

0

Komentarz do powyższej uwagi dla Dabblera jest prawidłowy. Ponieważ dodałeś domyślny obszar nazw do dokumentu XML, musisz także zmienić wyrażenie XPath, aby wyszukać węzły w nowej domyślnej przestrzeni nazw.

Nienumerowane nazwy w wyrażeniach XPath (np. AddressBook) są w przestrzeni nazw XML null, a nie domyślną przestrzenią nazw XML dokumentu.

Więc chcesz jakoś zarejestrować swój nowy obszar nazw za pomocą swojego obiektu xpath. Jak:

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

a następnie zmienić swoje wyrażenia XPath do:

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

Istnieje docs, w jaki sposób to zrobić z javax.xml.xpath API tutaj:

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

Jednak ja nie jestem pewien, jak to dokładnie przekłada się na Matlab.

+1

Masz rację! Powinienem zadeklarować nazwę ścieżki. Napisałem pytanie na forum Matlab. Zgłosić to, gdy tylko mi odpowiedzą. –

+0

Należy dokładnie tłumaczyć, ponieważ używa klas Java. – Nzbuu

+0

Dla implementacji specyficznej dla MATLAB, zamieściłem przykład w tym komentarzu na blogu: http://blogs.mathworks.com/desktop/2010/11/01/xml-and-matlab-navigating-a-tree/#comment- 8353 Nadal musisz używać klasy java dla NamespaceContext –

6

W przypadku nie można zarejestrować domyślnej przestrzeni nazw z towarzyszącym prefiksu, zastosowanie:

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

zamiast:

gpx/AddressBook/Entry/PhoneNumber 

Tutaj jest kompletny, XSLT oparte, weryfikacja:

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

kiedy ta transformacja jest stosowane na dostarczonym dokumencie 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> 

element poszukiwany jest wybierane i kopiowane do wyjścia:

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

Kod: 'e1 = xPath.compile ('* [nazwa() =" gpx "]/* [nazwa() =" trk "]"); s = e1.evaluate (gpx, XPathConstants.NODESET); sNumber = s.getLength; ' skompiluj i zwróć mi dokładną wartość. Podczas gdy 'e2 = xPath.compile ('* [nazwa() =" gpx "]/* [nazwa() =" trk [1] "]/* [nazwa() =" trkseg "]"); s = e2.ocena (gpx, XPathConstants.NODESET); sNumer = s.getLength; ' zawsze zwraca wartość 0. Czemu? Czy jest to "[1]" drugiego wyrażenia? –

+0

@Mariano: Oczywiście. Nazwy mogą zawierać jedynie znaki alfanumeryczne (zaczynające się od alfa) - a nie '[]'. Właściwie chcesz: '* [name() = 'trk'] [1]' –

+0

Jesteś mężczyzną! Ostatnia rzecz: co z atrybutem? Na przykład: jak mogę uzyskać szerokość i długość geograficzną z tym zapisem? Mam coś takiego jak 'gpx/trk [1]/trkseg [1]/trkpt [2]/@ lat', które muszę przepisać przy użyciu nazwy(). –