объявление xmlns сломало мой фильтр xPath

я понял действительно глупый фильтр xPath в MatLab:

% Construct the DOM.
docNode = xmlread('C:UsersMATLABtest.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 (в частности, a .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 ответов


комментарий дилетанта выше верен. Поскольку в XML-документ добавлено пространство имен по умолчанию, необходимо также изменить выражение XPath для поиска узлов в новом пространстве имен по умолчанию.

неквалифицированные имена в выражениях XPath (например,AddressBook) в null пространство имен XML, а не пространство имен XML по умолчанию документа.

таким образом, вы хотите каким-то образом зарегистрировать свое новое пространство имен с помощью


если вы не можете зарегистрировать пространство имен по умолчанию со связанным префиксом, используйте:

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