Почему мой XSL не находит ничего для обработки в этом XML?

Почему мой XSL не находит ничего для обработки в этом XML? Я пытаюсь преобразовать выходные данные отчета cognos xml в другую форму (да, я знаю, что cognos создает html, но мне нужно что-то еще). Он просто выводит слово «Заголовок:» и останавливается.

Вот мой XSL:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://developer.cognos.com/schemas/xmldata/1/" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">

    <xsl:template match="/">

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

    <xsl:template match="rowEdge">
        <b>Caption:</b> <xsl:value-of select="caption"/><br/>
        <xsl:if test="@id">
            <b>id:</b> <xsl:value-of select="@id"/><br/>
        </xsl:if>
        <xsl:if test="rowEdge">
            <xsl:apply-templates select="rowEdge"/>
        </xsl:if>
    </xsl:template>

    <html>
        <head><title>%s</title></head>
        <body>
            <xsl:apply-templates select="dataset/crosstab/rows"/>
        </body>
    </html>

    </xsl:template>
</xsl:stylesheet> 

Вот XML (мне пришлось удалить некоторые, но я должен дать представление):

<?xml version="1.0" encoding="utf-8" ?> 
 <dataset xmlns="http://developer.cognos.com/schemas/xmldata/1/" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
 <crosstab>
 <values>
  <value row="R1" col="C1" xs:nil="true" /> 
  <value row="R1" col="C2" xs:nil="true" /> 
  <value row="R1" col="C3" xs:nil="true" /> 
  <value row="R1" col="C4" xs:nil="true" /> 
  <value row="R1" col="C5" xs:nil="true" /> 
  <value row="R1" col="C6" xs:nil="true" /> 
  <value row="R1" col="C7" xs:nil="true" /> 
  <value row="R1" col="C8" xs:nil="true" /> 
  <value row="R1" col="C9" xs:nil="true" /> 
  <value row="R2" col="C1">0</value> 
  <value row="R2" col="C2">12.61728395</value> 
  <value row="R2" col="C3">1320.40677966</value> 
  <value row="R2" col="C4">7</value> 
  <value row="R2" col="C5">1.90318499</value> 
  <value row="R2" col="C6">108.66456135</value> 
  <value row="R2" col="C7">776.61407946</value> 
  <value row="R2" col="C8">-0.86007907</value> 
  <value row="R2" col="C9">46.53571429</value> 
</values>
 <corner>
  <caption>Time Period: DCG Incurred Paid Year</caption> 
  </corner>
 <columns>
 <colEdge>
  <caption>Jan 02 to Dec 02 {All Data} CRxIp</caption> 
 <colEdge>
  <caption>2002</caption> 
 <colEdge id="C1">
  <caption>Member Age Avg</caption> 
  </colEdge>
 <colEdge id="C2">
  <caption>Days Supply Per Script Rx</caption> 
  </colEdge>
 <colEdge id="C3">
  <caption>Net Pay Per Pat Med</caption> 
  </colEdge>
 <colEdge id="C4">
  <caption>Days LOS Admit Acute</caption> 
  </colEdge>
 <colEdge id="C5">
  <caption>Days LOS Admit Acute</caption> 
  </colEdge>
 <colEdge id="C6">
  <caption>Allow Amt PMPM Med and Rx {Cmpl}</caption> 
  </colEdge>
 <colEdge id="C7">
  <caption>Allow Amt PMPM Med and Rx {Cmpl}</caption> 
  </colEdge>
 <colEdge id="C8">
  <caption>% Diff Allow Amt PMPM Med and Rx {Cmpl}</caption> 
  </colEdge>
 <colEdge id="C9">
  <caption>Relative Risk Score Prosp Explan NonRescaled</caption> 
  </colEdge>
  </colEdge>
  </colEdge>
  </columns>
 <rows>
 <rowEdge>
  <caption>Subsets</caption> 
 <rowEdge>
  <caption>Plan Type Medstat</caption> 
 <rowEdge id="R1">
  <caption>Cohort Medstat</caption> 
  </rowEdge>
  </rowEdge>
  </rowEdge>
 <rowEdge>
  <caption>Chronic Episodes</caption> 
 <rowEdge>
  <caption>HMO (Managed Care)</caption> 
 <rowEdge id="R2">
  <caption>Females, Ages &lt; 1</caption> 
  </rowEdge>
</rowEdge>
 </rowEdge>
 </rows>
  </crosstab>
  </dataset>

person lkohl    schedule 22.05.2012    source источник
comment
Похоже, ваш корневой шаблон немного запутался - должна ли часть html внизу перейти к первому шаблону?   -  person Filburt    schedule 22.05.2012


Ответы (1)


В XSLT 1.0 (который вы используете) пространства имен по умолчанию не учитываются в выражениях XPath.

Что вам нужно сделать, это:

1) Назначьте префикс пространству имен по умолчанию вашего экземпляра документа в преобразовании XSLT, например:

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="cog:http://developer.cognos.com/schemas/xmldata/1/" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">

2) Используйте этот префикс перед каждым именем элемента (но не перед именами атрибутов) в выражениях XPath:

<xsl:template match="cog:rowEdge">
    <b>Caption:</b> <xsl:value-of select="cog:caption"/><br/>
    <xsl:if test="@id">
       <b>id:</b> <xsl:value-of select="@id"/><br/>
    </xsl:if>
    <xsl:if test="cog:rowEdge">
        <xsl:apply-templates select="cog:rowEdge"/>
    </xsl:if>
</xsl:template>

Примечание: вам не нужно проверять наличие cog:rowEdge перед применением шаблонов: apply-templates ничего не сделает, если в его атрибуте select в любом случае нет узлов;) ...

В таблице стилей есть еще несколько ошибок:

  1. Шаблоны не могут быть встроены
  2. В элементе xsl:stylesheet должен быть атрибут версии.

Правильная таблица стилей будет:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cog="http://developer.cognos.com/schemas/xmldata/1/" version="1.0">

    <xsl:template match="/">

        <html>
            <head>
                <title>%s</title>
            </head>
            <body>
                <xsl:apply-templates select="cog:dataset/cog:crosstab/cog:rows"/>
            </body>
        </html>

    </xsl:template>

    <xsl:template match="cog:rows">
        <xsl:apply-templates select="cog:rowEdge"/>
    </xsl:template>

    <xsl:template match="cog:rowEdge">
        <b>Caption:</b>
        <xsl:value-of select="cog:caption"/>
        <br/>
        <xsl:if test="@id">
            <b>id:</b>
            <xsl:value-of select="@id"/>
            <br/>
        </xsl:if>
        <xsl:apply-templates select="cog:rowEdge"/>
    </xsl:template>

</xsl:stylesheet>
person Eric van der Vlist    schedule 22.05.2012
comment
Спасибо. Мне также пришлось вызывать его следующим образом: ‹xsl:apply-templates select=cog:dataset/cog:crosstab/cog:rows/› - person lkohl; 22.05.2012
comment
Рекурсия не работает, она просто выводит весь текст (родительский + дочерний) этого первого rowEdge и завершает работу. - person lkohl; 22.05.2012
comment
Ну, я сосредоточился на проблеме с пространством имен, которая очень распространена, но, глядя на ваш XSLT, я вижу, что есть еще одна проблема: вы не можете встраивать шаблоны в шаблоны, как вы это делаете! Чтобы исправить это, вам нужно переместить встроенные шаблоны из шаблона для корневого узла (/) и добавить префикс перед всеми именами элементов во всех выражениях XPath. - person Eric van der Vlist; 22.05.2012