2016-08-12 2 views
0

Я пытаюсь отформатировать отчет в формате PDF при использовании apache fop, и я нашел поведение, которое я не могу понять.xsl: поведение совпадения шаблонов с и без пространства имен

При попытке отладить проблему, я отследил ее до поведения xsl директивы соответствия xsl: template, с и без пространства имен, объявленного в xml-файле.

Поведение xsl одинаково, даже если я использую другую имплантацию (xsltproc), поэтому разница должна быть в спецификации xsl, и она не связана с apache fop, но я не смог найти объяснения, поэтому я будут очень благодарны, если кто-то может мне помочь.

Вот код. FIrst файл "bugger.xml":

<?xml version="1.0" encoding="UTF-8" ?> 
<parent xmlns="http://www.bugger.org">parent_value</parent> 

А вот "bugger.xsl" Файл:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0"> 
<xsl:output indent="yes"/> 

<xsl:template match="/"> 
    OK, root element matches... 
    <xsl:apply-templates /> 
</xsl:template> 

<xsl:template match="/*"> 
    you WILL see this writing... I'm a parent tag, look: I'm a "<xsl:value-of select="name()"/>", why you cannot see me in the /parent template match? 
    The naming match fails because of the xmlns directive in the bugger.xml file. If you remove it, all works fine. 
</xsl:template> 

<xsl:template match="/parent"> 
    you will NOT see this writing, while you should see it... 
</xsl:template> 

</xsl:stylesheet> 

Возникает вопрос: почему, если я помещаю Xmlns = "HTTP: // www.bugger.org ", шаблон xsl: template соответствует«/* », и если я его удалю, шаблон xsl: соответствует«/parent »?

Спасибо за помощь!

+0

Спасибо вам обоим michael.hor257k и Тони Грэхем. Я старательно предпочитаю ответ Тони, потому что он дает немного больше контекста, но оба ответа обогатили мои знания. – arzillo

+0

На самом деле, я уже понял, что проблема была в пространстве имен, но мне не хватало xmlns: b = "http://www.bugger.org", а затем b: parent, который Тони включил в свой ответ. Гоша, ребята, вы очень круты, спасибо снова !!! – arzillo

ответ

1

С:

<parent xmlns="http://www.bugger.org">parent_value</parent> 

вы установили 'пространство имен по умолчанию' к 'http://www.bugger.org' URI пространства имен. См. https://www.w3.org/TR/REC-xml-names/#defaulting

Процессор XSLT (и все, что реализует имена REC-xml, обрабатывающие ваш XML), видит «родительский» элемент как «in» (а не технический термин) в пространстве имен «http://www.bugger.org».

В вашей таблице стилей /* соответствует, так как * (в этом контексте) соответствует всем элементам. /parent не соответствует, поскольку это соответствует только parent с нулевым URI пространства имен (именно поэтому он сопоставлен при удалении объявления пространства имен). См https://www.w3.org/TR/xpath/#node-tests

(Кроме того, в таблице стилей, которые вы показываете, что вам не нужно ведущий / в вашей модели матча.)

Чтобы соответствовать специально на parent с «http://www.bugger.org» URI пространства имен, что вам нужно для соответствия «квалифицированному имени» (QName) для элемента. Т.е. вам нужно использовать префикс пространства имен с parent в шаблонах совпадений, хотя вы можете использовать тот же самый URI пространства имен, что и пространство имен по умолчанию в исходном XML (поскольку в XSLT неквалифицированные имена в шаблонах всегда находятся в пустом пространстве имен):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:fo="http://www.w3.org/1999/XSL/Format" 
       xmlns:b="http://www.bugger.org" 
       version="1.0" 
       exclude-result-prefixes="b"> 

<xsl:template match="b:*"> 
    you will NOT see this writing, because it has a lower priority... 
</xsl:template> 

<xsl:template match="b:parent"> 
    you will see this writing. 
</xsl:template> 

</xsl:stylesheet> 
+0

"* Вам не нужны ведущие'/'в шаблонах совпадений * * * * * хорошая практика включать'/'при сопоставлении корневого элемента. Это необходимо, если есть другие элементы с тем же именем, для которых требуется другое обращение. –

+0

Следовательно, «в таблице стилей, которую вы показываете». Все зависит от проблемы, которую вы решаете. Конечно, вы хотите добавить дополнительный контекст (или использовать разные режимы), если хотите по-разному обрабатывать один и тот же элемент в разных местах. '/ element' vs '*/element' (не то, чтобы вы пишете шаблон соответствия таким образом) является одним из примеров. Если, например, вы трансформируетесь в XSL-FO с одной последовательностью страниц, а шаблон для '/' генерирует все: от fo: root' до fo: page-sequence', тогда вам может быть безразлично, если 'element' может отображаться как элемент документа, а также отображаться в другом месте. –

1

Когда источник:

<?xml version="1.0" encoding="UTF-8" ?> 
<parent xmlns="http://www.bugger.org">parent_value</parent> 

этот шаблон:

<xsl:template match="/parent"> 
    you will NOT see this writing, while you should see it... 
</xsl:template> 

ничего в файле XML-источника не совпадают, и не будет применяться. Ото, этот шаблон:

<xsl:template match="/*"> 
    you WILL see this writing... I'm a parent tag, look: I'm a "<xsl:value-of select="name()"/>", why you cannot see me in the /parent template match? 
    The naming match fails because of the xmlns directive in the bugger.xml file. If you remove it, all works fine. 
</xsl:template> 

ли соответствует корневому элементу (чей локального имя является parent в данном примере), и, следовательно, будет применяться к нему.


Теперь, когда ваш источник:

<?xml version="1.0" encoding="UTF-8" ?> 
<parent>parent_value</parent> 

затем оба шаблонов соответствуют корневым parent элемента - и с тем же приоритетом (0,5). В таком случае процессор будет выбрать последний из шаблонов соответствия - см: https://www.w3.org/TR/xslt/#conflict


Примечание:

  1. / является корневой узел, не корень элемент.

  2. «XMLNS =» http://www.bugger.org «директива» называется имен декларации а - и вы бы посоветовать, чтобы узнать больше о пространствах имен XML и как обрабатывать их в XSLT.