Как заставить работать Coldfusion XSLT «содержит» функцию? - PullRequest
3 голосов
/ 20 декабря 2010

Я пытаюсь преобразовать дамп XML, похожий на этот

<?xml version="1.0" encoding="UTF-8"?>
<report>
    <report_header>
        <c1>desc</c1>
        <c2>prname</c2>
        <c3>prnum</c3>
        <c4>cdate</c4>
        <c5>phase</c5>
        <c6>stype</c6>
        <c7>status</c7>
        <c8>parent</c8>
        <c9>location</c9>
    </report_header>
    <report_row>
        <c1></c1>
        <c2>IT Project Message Validation</c2>
        <c3>IT-0000021</c3>
        <c4>12/14/2010 09:56 AM</c4>
        <c5>Preparation</c5>
        <c6>IT Projects</c6>
        <c7>Active</c7>
        <c8>IT</c8>
        <c9>/IT/BIOMED</c9>
    </report_row>
    <report_row>
        <c1></c1>
        <c2>David, Michael John Morning QA Test</c2>
        <c3>IT-0000020</c3>
        <c4>12/14/2010 08:12 AM</c4>
        <c5>Preparation</c5>
        <c6>IT Projects</c6>
        <c7>Active</c7>
        <c8>IT</c8>
        <c9>/IT/BIOMED</c9>
    </report_row>
</report>

с xslt ниже, в csv. К сожалению, функция содержит не работает.

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="report">
        <xsl:apply-templates select="report_header"/>
        <xsl:apply-templates select="report_row"/>
    </xsl:template>

    <xsl:template match="report_header">
        <xsl:for-each select="*">
            <xsl:value-of select="."/>
            <xsl:if test="position() != last()">
                <xsl:value-of select="','"/>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>
        </xsl:text>
    </xsl:template>

    <xsl:template match="report_row">
        <xsl:param name="value" />
        <xsl:for-each select="*">
            <xsl:value-of select="$value" />
            <xsl:if test="(contains($value,','))">
                <xsl:text>"</xsl:text><xsl:value-of select="."/><xsl:text>"</xsl:text>
            </xsl:if>
            <xsl:if test="not(contains($value,','))">
                <xsl:value-of select="."/>
            </xsl:if>
            <xsl:if test="position() != last()">
                <xsl:value-of select="','"/>
            </xsl:if>
        </xsl:for-each>
        <xsl:if test="position() != last()">
            <xsl:text>
            </xsl:text>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

Я получаю следующий дамп. Я ожидал квалификаторов вокруг столбца prname во втором ряду.

desc,prname,prnum,cdate,phase,stype,status,parent,location
        ,IT Project Message Validation,IT-0000021,12/14/2010 09:56 AM,Preparation,IT Projects,Active,IT,/IT/BIOMED
            ,David, Michael John Morning QA Test,IT-0000020,12/14/2010 08:12 AM,Preparation,IT Projects,Active,IT,/IT/BIOMED

Я использовал только функцию xmltransform coldfusion для проверки.

Ответы [ 2 ]

2 голосов
/ 20 декабря 2010

В предоставленном коде есть проблемы , о некоторых из них сообщили в ответе Мадс Хансен.

Основная проблема в том, что код неоправданно сложен .

Ниже приведено простое решение, которое производит то, что кажется нужным :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="report_header/*">
            <xsl:value-of select="."/>
            <xsl:call-template name="processEnd"/>
    </xsl:template>

    <xsl:template match="report_row/*[contains(., ',')]">
                <xsl:text>"</xsl:text>
                <xsl:value-of select="."/>
                <xsl:text>"</xsl:text>
            <xsl:call-template name="processEnd"/>
    </xsl:template>

    <xsl:template match="report_row/*[not(contains(., ','))]">
                <xsl:value-of select="."/>
            <xsl:call-template name="processEnd"/>
    </xsl:template>

    <xsl:template name="processEnd">
      <xsl:choose>
          <xsl:when test="position() != last()">,</xsl:when>
          <xsl:otherwise><xsl:text>             </xsl:text></xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<report>
    <report_header>
        <c1>desc</c1>
        <c2>prname</c2>
        <c3>prnum</c3>
        <c4>cdate</c4>
        <c5>phase</c5>
        <c6>stype</c6>
        <c7>status</c7>
        <c8>parent</c8>
        <c9>location</c9>
    </report_header>
    <report_row>
        <c1></c1>
        <c2>IT Project Message Validation</c2>
        <c3>IT-0000021</c3>
        <c4>12/14/2010 09:56 AM</c4>
        <c5>Preparation</c5>
        <c6>IT Projects</c6>
        <c7>Active</c7>
        <c8>IT</c8>
        <c9>/IT/BIOMED</c9>
    </report_row>
    <report_row>
        <c1></c1>
        <c2>David, Michael John Morning QA Test</c2>
        <c3>IT-0000020</c3>
        <c4>12/14/2010 08:12 AM</c4>
        <c5>Preparation</c5>
        <c6>IT Projects</c6>
        <c7>Active</c7>
        <c8>IT</c8>
        <c9>/IT/BIOMED</c9>
    </report_row>
</report>

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

desc,prname,prnum,cdate,phase,stype,status,parent,location             ,IT Project Message Validation,IT-0000021,12/14/2010 09:56 AM,Preparation,IT Projects,Active,IT,/IT/BIOMED             ,"David, Michael John Morning QA Test",IT-0000020,12/14/2010 08:12 AM,Preparation,IT Projects,Active,IT,/IT/BIOMED             
1 голос
/ 20 декабря 2010

Не думаю, что contains() - это ваша проблема.

Проблема в том, что ваш шаблон report_row имеет <xsl:param name="value"/>, которому никогда не присваивается значение.У вас есть логика, которая основана на этом параметре, который никогда не срабатывает.Поскольку $value пусто, оно никогда не будет contain() , или любым другим символом.

Вы можете получить желаемое поведение, добавив атрибут select к xsl:param:

  <xsl:template match="report_row">
        <xsl:param name="value" select="." />

Вы могли бы упростить свою таблицу стилей и логику, сделав больше стиль «push», который легче отлаживать и поддерживать, чем таблицы стилей «pull», которые пытаются реализовать процедурную логику в XSLT.* Что-то вроде следующей таблицы стилей позволяет добиться того же:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:apply-templates select="*/report_header/*"/>
        <xsl:apply-templates select="*/report_row/*"/>
    </xsl:template>

    <!-- For all but the last item, apply templates for the content, then add a comma -->
    <xsl:template match="*[following-sibling::*]">
        <xsl:apply-templates/>
        <xsl:text>,</xsl:text>
    </xsl:template>

    <!-- If it's the last element in a group, add a newline char -->
    <xsl:template match="*[not(following-sibling::*)]">
       <xsl:apply-templates />
        <!--Line break-->
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

    <!-- If any values contains a comma, wrap it in quotes -->
    <xsl:template match="text()[contains(.,',')]">
        <xsl:text>"</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>"</xsl:text>
    </xsl:template>

</xsl:stylesheet>

Создает следующий вывод:

desc,prname,prnum,cdate,phase,stype,status,parent,location
,IT Project Message Validation,IT-0000021,12/14/2010 09:56 AM,Preparation,IT Projects,Active,IT,/IT/BIOMED
,"David, Michael John Morning QA Test",IT-0000020,12/14/2010 08:12 AM,Preparation,IT Projects,Active,IT,/IT/BIOMED
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...