Использовать (при условии, что предоставленный фрагмент XML является дочерним элементом текущего узла и существует только один элемент с требуемым свойством):
substring-before(*[not(starts-with(., 'info:eu-repo'))], '-')
Проверка на основе XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:copy-of select=
"substring-before(*[not(starts-with(., 'info:eu-repo'))], '-') "/>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к следующему XML-документу (предоставленный фрагмент заключен в один верхний элемент и объявлено пространство имен):
<t xmlns:dc="some:dc">
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2012-07-04</dc:date>
</t>
выражение XPath оценивается для верхнего элемента, и результат этой оценки копируется в выходные данные:
2012
II. Более одного элемента с нужным свойством:
В этом случае невозможно получить нужные данные с помощью одного выражения XPath 1.0.
Это преобразование XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(starts-with(., 'info:eu-repo'))]/text()">
<xsl:copy-of select="substring-before(., '-') "/>
==============
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
при применении к этому XML-документу:
<t xmlns:dc="some:dc">
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2012-07-04</dc:date>
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2011-07-05</dc:date>
</t>
выдает желаемый правильный результат:
2012
==============
2011
==============
III. Однострочный XPath 2.0
*[not(starts-with(., 'info:eu-repo'))]/substring-before(., '-')
Когда это выражение XPath 2.0 оценивается по верхнему элементу последнего XML-документа (ближайший вверху), создаются требуемые годы:
2012 2011
Проверка на основе XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:sequence select=
"*[not(starts-with(., 'info:eu-repo'))]/substring-before(., '-')"/>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к последнему XML-документу, вычисляется выражение XPath, и результат этой оценки копируется в выходные данные:
2012 2011
IV. Самый общий и сложный случай:
Теперь давайте получим этот XML-документ:
<t xmlns:dc="some:dc">
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2012-07-04</dc:date>
<dc:date>info:eu-repo/date/embargoEnd/2013-06-12</dc:date>
<dc:date>2011-07-05</dc:date>
<dc:date>*/date/embargoEnd/2014-06-12</dc:date>
</t>
Мы по-прежнему хотим получить часть года для всех элементов dc:date
, строковое значение которых не начинается с 'info:eu-repo'. Однако ни одно из предыдущих решений не работает правильно с последним элементом dc:date
выше.
Примечательно, что нужные данные все еще можно получить с помощью одного выражения XPAth 2.0:
for $s in
*[not(starts-with(., 'info:eu-repo'))]/tokenize(.,'/')[last()]
return
substring-before($s, '-')
Когда это выражение оценивается по верхнему элементу вышеуказанного XML-документа, создается желаемый правильный результат:
2012 2011 2014
А это проверка на основе XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:sequence select=
"for $s in
*[not(starts-with(., 'info:eu-repo'))]/tokenize(.,'/')[last()]
return
substring-before($s, '-')
"/>
</xsl:template>
</xsl:stylesheet>
person
Dimitre Novatchev
schedule
20.09.2012