#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