Как построить строку с помощью XSLT?

У меня есть этот фрагмент XML

<MediaTypes>
  <DVD>true</DVD>
  <HDDVD>false</HDDVD>
  <BluRay>true</BluRay>
</MediaTypes>

И я хочу создать вывод, который выглядит так

DVD / Blu-ray

или вот так

DVD

или вот так

DVD / HD-DVD / Blu-ray

в зависимости от истинного/ложного состояний

Но я совсем новичок в игре XSLT. :-/

Вот фрагмент полного XML

<?xml version="1.0" encoding="Windows-1252"?>
<Collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <DVD>
    <ProfileTimestamp>2012-06-07T05:20:51Z</ProfileTimestamp>
    <ID>0044005507027.5</ID>
    <MediaTypes>
      <DVD>true</DVD>
      <HDDVD>false</HDDVD>
      <BluRay>false</BluRay>
    </MediaTypes>
    <UPC>0-044005-507027</UPC>
    <CollectionNumber>448</CollectionNumber>
    <CollectionType IsPartOfOwnedCollection="true">Owned</CollectionType>
    <Title>The Big Lebowski</Title>
    <DistTrait />
    <OriginalTitle />
    <CountryOfOrigin>United States</CountryOfOrigin>
    ...
  </DVD>
  <DVD>
     ...
  </DVD>
</Collection>

Я попытался следовать приведенным ниже советам (относительно цикла), но, похоже, это не сработало.

Это XSL, который у меня есть (полный):

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

    <xsl:template name="MediaTypes" match="MediaTypes">
        Test
        <xsl:for-each select="*[.='true']">            
            <xsl:value-of select="name()"/>
            <xsl:if test="position()!=last()">
                <xsl:text>/</xsl:text>
            </xsl:if>
        </xsl:for-each>        
    </xsl:template>

    <xsl:template match="/">
        <html>
            <head>
                <title>DVD Profiler Double Dips</title>
            </head>
            <body>
                <div>
                    <h1>DVD Profiler Double Dips</h1>
                </div>
                <table border="1" cellpadding="3" cellspacing="0">
                    <tr>
                        <th>Title</th>
                        <th>Edition</th>
                        <th>Production Year</th>
                        <th>DVD /</th>
                        <th>Purchase Date</th>
                        <th>Collection Type</th>
                        <th>Original Title</th>
                        <th>Sort Title</th>
                    </tr>
                    <xsl:for-each select="/Collection/DVD">
                        <tr>
                            <td>
                                <xsl:value-of select="Title"/>
                            </td>
                            <td>
                                <xsl:if test="DistTrait != ''">
                                    <xsl:value-of select="DistTrait"/>
                                </xsl:if>
                                <xsl:if test="DistTrait = ''">
                                    &#160;
                                </xsl:if>
                            </td>
                            <td>
                                <xsl:if test="ProductionYear != ''">
                                    <xsl:value-of select="ProductionYear"/>
                                </xsl:if>
                                <xsl:if test="ProductionYear = ''">
                                    &#160;
                                </xsl:if>
                            </td>
                            <td>
                                <xsl:call-template name="MediaTypes" />
                            </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

Но где

<xsl:call-template name="MediaTypes" />

стоит, выходит только "Тест"

Ура!

Вы, ребята, потрясающие. Да

<xsl:apply-templates select="MediaTypes"/>

Был моим любимым оружием.

Мой окончательный шаблон выглядит так:

<xsl:template name="MediaTypes" match="MediaTypes">
    <xsl:for-each select="*[.='true']">
        <xsl:value-of select="name()"/>
        <xsl:if test="position()!=last()">
            <xsl:text> / </xsl:text>
        </xsl:if>
    </xsl:for-each>
    <xsl:if test="CustomMediaType != ''">
        <xsl:if test="*[.='true']">
            <xsl:text> / </xsl:text>
        </xsl:if>
        <xsl:value-of select="CustomMediaType"/>
    </xsl:if>
</xsl:template>

начинает понимать, как все работает

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


person Dee J. Doena    schedule 19.03.2014    source источник
comment
Какая версия XSLT? Можете ли вы использовать 2.0 или вы ограничены 1.0, и если 1.0, то какой процессор XSLT вы будете использовать?   -  person Ian Roberts    schedule 19.03.2014
comment
Хм, так вы хотите использовать элементы, а не их содержимое в качестве вывода? Это немного необычно   -  person Eric Herlitz    schedule 19.03.2014
comment
@IanRoberts Я хочу поместить этот XSL в заголовок XML-файла, а затем любой браузер покажет мне HTML.   -  person Dee J. Doena    schedule 19.03.2014
comment
@EricHerlitz Это так? Как я уже сказал, я новичок в XSL. Я пришел из мира классического программирования. :-/   -  person Dee J. Doena    schedule 19.03.2014
comment
В этом случае ответ 1.0 - насколько мне известно, нет браузера, который изначально реализует 2.0 (и даже если бы он был, вам нужно было бы придерживаться 1.0, чтобы работать с ними всеми).   -  person Ian Roberts    schedule 19.03.2014


Ответы (2)


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

Вот шаблон для соответствия любому элементу <MediaTypes> и вывода необходимой строки; надеюсь, вы знаете, как включить его в свою собственную таблицу стилей:

<xsl:template match="MediaTypes">
    <xsl:for-each select="*[.='true']">
        <xsl:value-of select="name()"/>
        <xsl:if test="position()!=last()">
            <xsl:text>/</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>
person michael.hor257k    schedule 19.03.2014
comment
Я пробовал это, но, похоже, он не входит в цикл for-each. Я ввел это в свой код ‹xsl:template name=MediaTypes match=MediaTypes› ‹xsl:for-each select=*[.= 'true']› Test ‹xsl:value-of select=name()/› ‹xsl:if test=position()!=last()› ‹xsl:text›/‹/xsl:text› ‹/xsl: if› ‹/xsl:for-each› и позже, когда мне это нужно, я написал ‹xsl:call-template name=MediaTypes /› Но единственным выходом является Test :-( - person Dee J. Doena; 19.03.2014
comment
@DeeJ.Doena вам, вероятно, нужно использовать apply-templates вместо call-template, чтобы убедиться, что узел контекста правильный - с <xsl:call-template name="MediaTypes"/> узел контекста останется таким, каким он был в момент вызова, но с <xsl:apply-templates select="path/to/MediaTypes"/> он правильно сбросит контекст к элементу MediaTypes. - person Ian Roberts; 19.03.2014
comment
@DeeJ.Doena Я предлагаю вам отредактировать свой вопрос, включив в него XSLT и результат, который вы надеетесь получить (в виде кода). - person michael.hor257k; 19.03.2014
comment
@DeeJ.Doena Как предложил Ян Робертс, просто добавьте мой шаблон как есть в свою таблицу стилей и замените <xsl:call-template name="MediaTypes"/> на <xsl:apply-templates select="MediaTypes"/>. - person michael.hor257k; 19.03.2014

Я бы посоветовал вам немного изменить xml

Вот пример

<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" ?>
<MediaTypes>
    <Media name="DVD">true</Media>
    <Media name="HDDVD">false</Media>
    <Media name="BluRay">true</Media>
</MediaTypes>

Таким образом, вы можете написать выражения XPATH, такие как //MediaTypes/Media Однако @michael.hor257k написал хорошее решение, вставив этот шаблон xml в это, которое будет выглядеть так

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="//MediaTypes">
        <xsl:for-each select="*[.='true']">
            <xsl:value-of select="@name"/>
            <xsl:if test="position()!=last()">
                <xsl:text>/</xsl:text>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Это отобразит DVD/BluRay

Проверьте здесь http://xslttest.appspot.com/

person Eric Herlitz    schedule 19.03.2014
comment
Спасибо, но, к сожалению, XML не мой :-/ - person Dee J. Doena; 19.03.2014