XSLT - 使用当前节点的完整XML路径打印错误消息

时间:2014-12-15 21:31:18

标签: xml xslt error-handling

假设我有一个XML:

<?xml version="1.0" encoding="UTF-8"?>
<catalogs>
    <catalog id="1">
        <cd id="1">
            <title>Empire Burlesque</title>
            <artist>Bob Dylan</artist>
            <country>USA</country>
            <company>Columbia</company>
            <price>10.90</price>
            <year>1985</year>
        </cd>
        <cd id="2">
            <title>Hide your heart</title>
            <artist>Bonnie Tyler</artist>
            <country>UK</country>
            <company>CBS Records</company>
            <price>9.90</price>
            <year>1988</year>
        </cd>
    </catalog>
    <catalog id="2">
        <cd id="3">
            <title>Sylvias Mother</title>
            <artist>Dr.Hook</artist>
            <country>UK</country>
            <company>CBS</company>
            <price>8.10</price>
            <year>1973</year>
        </cd>
        <cd id="4">
            <title>Maggie May</title>
            <artist>Rod Stewart</artist>
            <country>UK</country>
            <company>Pickwick</company>
            <price>8.50</price>
            <year>1990</year>
        </cd>
    </catalog>
</catalogs>

我正在迭代它,我想在失败时打印一条消息导致终止。 我希望我的消息包含当前节点及其祖先。 例如:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <html>
            <body>
                <xsl:for-each select="catalogs/catalog/cd">
                        Title: <xsl:value-of select="title"/>
                    <br />
                    <xsl:if test="artist='Dr.Hook'">
                        <xsl:message terminate="yes">TERMINATE Message with current node and its ancestors</xsl:message>
                    </xsl:if>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

我希望终止消息类似于:

Termination Location - <artist>Dr.Hook</artist> ; <cd id="3"> ; <catalog id="2"> ; <catalogs>

2 个答案:

答案 0 :(得分:1)

我想你可能需要一个递归模板。您将无法在模板中使用xsl:copy,因此您必须将元素名称输出为文本。

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="/">
      <html>
         <body>
            <xsl:for-each select="catalogs/catalog/cd"> Title: 
               <xsl:value-of select="title"/>
               <br/>
               <xsl:if test="artist='Dr.Hook'">
                  <xsl:message terminate="yes"> TERMINATE Message with current node and its ancestors 
                     <xsl:apply-templates select="." mode="message"/></xsl:message>
               </xsl:if></xsl:for-each>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="*" mode="message">
      <xsl:value-of select="concat('&lt;', name())"/>
      <xsl:for-each select="@*">
         <xsl:value-of select="concat(' ', name(), '=&quot;', ., '&quot;')"/>
      </xsl:for-each>
      <xsl:value-of select="'&gt;'"/>
      <xsl:apply-templates select="parent::*" mode="message"/>
   </xsl:template>
</xsl:stylesheet>

请注意,他不会输出artist元素,因为您当前的上下文是cd节点,而不是artist节点。

答案 1 :(得分:0)

我建议你这样试试:

XSLT 1.0

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

<xsl:template match="/">
    <html>
        <body>
            <xsl:for-each select="catalogs/catalog/cd">
                <xsl:text>Title: </xsl:text>
                <xsl:value-of select="title"/>
                <br/>

                <xsl:if test="artist='Dr.Hook'">
                    <xsl:message terminate="yes">
                        <xsl:for-each select="ancestor-or-self::*">
                            <xsl:value-of select="local-name()"/>
                            <xsl:if test="@id">
                                <xsl:value-of select="concat('[id=', @id, ']')"/>
                            </xsl:if>
                            <xsl:text>/</xsl:text>
                            <xsl:value-of select="artist"/>
                        </xsl:for-each>
                    </xsl:message>
                </xsl:if>

            </xsl:for-each>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>

您的示例中收到的消息将是:

catalogs/catalog[id=2]/cd[id=3]/Dr.Hook