объявление xmlns нарушило мой фильтр XPath

#xml #matlab #xpath

#xml #matlab #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 (в частности, с файлом .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

Почему? Как я могу избежать этой ошибки?

Комментарии:

1. Я не знаю MatLab, но с точки зрения XML теперь вы разместили свой элемент gpx (и т. Д.) В topografix.com/GPX/1/1 пространство имен, и XPath ищет его в глобальном пространстве имен. Вам нужно каким-то образом сделать пространство имен известным MatLab, а затем указать элемент gpx в выражении XPath.

2. Хороший вопрос, 1. В случае, если у вас нет механизмов в Matlab для регистрации пространства имен, вы всегда можете использовать выражение, подобное этому: *[name()= 'gpx'] /*[name()='AddressBook'] /*[name()='Entry'] /*[name() = 'PhoneNumber']

3. @_Mariano: Был ли мой ответ полезным?

Ответ №1:

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

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

Комментарии:

1. Код: 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]’ второго выражения?

2. @Mariano: Конечно. Имена могут содержать только буквенно-цифровые символы (начиная с альфа) — нет [] . Вы действительно хотите: *[name()='trk'][1]

3. Ты мужчина! Последнее: как насчет атрибута? Например: как я могу получить широту и долготу с помощью этой записи? У меня есть что-то подобное gpx/trk[1]/trkseg[1]/trkpt[2]/@lat , что мне нужно переписать с помощью name().

4. @Mariano: lat в предоставленном вами XML-документе нет атрибутов (а также атрибутов с именами, которые могли бы указывать долготу. Так что это только мое предположение , что я не видел XML-документ, указанный для — use: *[name()='gpx']/*[name()='trk'][1]/*[name()='trkseg'][1]/*[name()='trkpt'][2]/@lat

5. Посмотрите на это: en.wikipedia.org/wiki/GPS_eXchange_Format Атрибуты «lat» и «lon» записываются внутри trkpt тега. В любом случае вы были правы! 😉

Ответ №2:

Комментарий дилетанта выше верен. Поскольку вы добавили пространство имен по умолчанию в свой 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. Я сообщу об этом, как только они мне ответят.

2. Должен точно переводиться, потому что он использует классы Java.

3. Для реализации, специфичной для MATLAB, я опубликовал пример в этом комментарии к блогу: blogs.mathworks.com/desktop/2010/11/01/… Вам все равно нужно использовать класс Java для NamespaceContext