2011-01-25 4 views
5

привет У меня есть XML-документ сайта, который выглядит примерно такXSLT копирования из без детей

<pagenode title="home" url="~/" fornavbar="true"> 
<pagenode title="admin" url="~/admin" fornavbar="false"> 
    <pagenode title="users" url="~/admin/users" fornavbar="false"/> 
    <pagenode title="events" url="~/admin/events" fornavbar="true"/> 
</pagenode> 
<pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
<pagenode title="contact us" url="~/contactus" fornavbar="false"/> 
</pagenode> 

Теперь я хочу, чтобы извлечь документ XML для навигационной панели, которая включает в себя все pagenodes, которые имеют fornavbar = правда. Как это может быть сделано?

ближайший я смог получить до сих пор было так:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:template match="pagenode[@fornavbar='true']"> 
    <xsl:copy-of select="."/> 
</xsl:template> 
</xsl:stylesheet> 

проблема с этим состоит в том, что включает в себя все дети ничего совпавшие в навигационной панели

я только хочу, чтобы скопировать все атрибуты , не все дети

но если я попробовать

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:template match="pagenode[@fornavbar='true']"> 
    <pagenode title="{@title}" url="{@url}"/> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

то у меня есть 2 проблемы

  1. я мог бы впечатать каждый атрибут отдельно, и у меня есть довольно много на странице и Theyre склонны в конечном счете
  2. изменить теряет иерархию. все становится плоским один за другим

Я был бы признателен всем и любой помощи в этом вопросе.

спасибо!

EDIT: пример вывода, который ид нравится видеть

<pagenode title="home" url="~/" fornavbar="true"> 
<pagenode title="events" url="~/admin/events" fornavbar="true"/> 
<pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
</pagenode> 
+0

Хороший вопрос, +1. См. Мой ответ для полного, но очень короткого решения, которое полностью использует самый фундаментальный шаблон проектирования XSLT. :) –

ответ

2

вы можете перебрать атрибутов узла с помощью xsl:foreach select="@*" таким образом, вы не должны копировать атрибуты вручную. если вы вызываете xsl:apply-templates внутри элемента yor pagenode, вы должны получить желаемый результат.

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="pagenode[@fornavbar='true']"> 
     <pagenode> 
      <xsl:for-each select="@*"> 
       <xsl:attribute name="{name(.)}"><xsl:value-of select="."/></xsl:attribute> 
      </xsl:for-each> 
      <xsl:apply-templates/> 
     </pagenode> 
    </xsl:template> 
</xsl:stylesheet> 

делает

<?xml version="1.0"?> 
<pagenode title="home" url="~/" fornavbar="true"> 
    <pagenode title="events" url="~/admin/events" fornavbar="true"/> 
    <pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
</pagenode> 
+1

'' гораздо более кратким –

+0

спасибо миллион! он работает именно то, что мне нужно !!! ваше превосходное! –

1

XSLT должен выглядеть следующим образом:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="pagenode[@fornavbar='true']"> 
    <pagenode> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates/> 
    </pagenode> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Должно быть, остатки моего теста. – akond

+0

+1 Для простейшей коррекции. –

3

Это, вероятно, самый короткий и чистейшей 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="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*[@fornavbar = 'false']"> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

, когда это преобразование применяются на предоставленном документе XML:

<pagenode title="home" url="~/" fornavbar="true"> 
    <pagenode title="admin" url="~/admin" fornavbar="false"> 
     <pagenode title="users" url="~/admin/users" fornavbar="false"/> 
     <pagenode title="events" url="~/admin/events" fornavbar="true"/> 
    </pagenode> 
    <pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
    <pagenode title="contact us" url="~/contactus" fornavbar="false"/> 
</pagenode> 

производится разыскиваемый, правильный результат:

<pagenode title="home" url="~/" fornavbar="true"> 
    <pagenode title="events" url="~/admin/events" fornavbar="true"/> 
    <pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
</pagenode> 

Объяснение:

  1. Правило идентичности (шаблон) копирует каждый узел «как есть». Использование identity rule и переопределение это самый фундаментальный шаблон дизайна XSLT.

  2. Существует один шаблон, который отменяет правила идентичности - для элементов, fornavbar атрибут "false". Здесь указанное действие - применить шаблоны к дочерним элементам текущего элемента.

+1

+1 Хороший ответ. Просто для семантической и как обратная логика одного решения только для правил я бы использовал '* [not (self :: pagenode/@ fornavbar = 'true')]' –

+0

@Alejandro: Спасибо. Что вы имеете в виду? –

+0

Я имею в виду, что правило обхода будет соответствовать любому элементу с атрибутом '@ fornavbar' с строковым значением' 'false'', поэтому правило идентификации будет соответствовать ** любому элементу **, не имеющему атрибут' @ fornavbar', с '' false 'string, вместо 'pagenode' элементов ** ** **, имеющих атрибут' @ fornavbar' с строковым значением '' true''. –

 Смежные вопросы

  • Нет связанных вопросов^_^