Removing Attributes from XSLT and working with result set

前端 未结 3 1794
渐次进展
渐次进展 2020-12-21 04:58

Is it possible to remove xml attributes from XSLT AND work with the resulting transform?

In other words, I have the following XML:



        
相关标签:
3条回答
  • 2020-12-21 05:31

    There is something odd in this question: I don't see how the title of your question does match the contents.

    In the title you are asking for a two-pass transform where the first pass must remove the attributes and the second must work on it.

    In the contents you show two templates which outputs the local name of the nodes and attributes and, after, you show in another template that you'd like to work with the attributes getting their value... :)

    As per @Dimitre's answer replied to the contents of your question (which does not address a real question I think) I will try to answer the title of your question, which seems much more interesting (and answerable).


    Removing Attributes from XSLT ...

    To remove the attributes (and obtain a transform without namespaces) you can work with an Identity Transformation. Because you want multi-pass you must copy the content of the transformation on a variable in the first pass.

    You can use modes to address the process to the elements in the first pass.

    ... and working with result set

    To work with result set (formally known as a result tree fragment) you need to apply the templates using a reference to the variable defined in the first pass. Welcome! This is the second pass :)

    Two pass transformation is relatively much accessible in XSLT 2.0 than in XSLT 1.0, because of the XSLT 2.0 ability to apply templates to an RTF. In XSLT 1.0 you will need a specific extension function called node-set().


    The XSLT 2.0 will look like this (pure example):

    <xsl:stylesheet   
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   
        xmlns:x="abc123"   
        version="2.0">
    
        <xsl:output indent="yes" omit-xml-declaration="yes"/>   
        <xsl:strip-space elements="*"/> 
    
        <xsl:template match="/">
            <xsl:variable name="FirstPass">
                <xsl:copy>
                    <xsl:apply-templates select="/" mode="FirstPass"/>
                </xsl:copy>
            </xsl:variable>
    
            <xsl:apply-templates select="$FirstPass/report/book/page"/>
        </xsl:template>
    
        <xsl:template match="node()" mode="FirstPass">
            <xsl:element name="{local-name()}">
                <xsl:apply-templates select ="node()" mode="FirstPass"/>
            </xsl:element>
        </xsl:template>
    
        <xsl:template match="page">
            <xsl:value-of select="count(@*)"/>
        </xsl:template>
    
    </xsl:stylesheet> 
    

    with results (applied on your input example)

    00
    

    The XSLT 1.0 will look very similar, but the transform root element:

    <xsl:stylesheet   
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   
    xmlns:x="abc123"
    xmlns:exslt="http://exslt.org/common"
    version="2.0">
    

    and the second pass:

     <xsl:apply-templates select="exslt:node-set($FirstPass)/report/book/page"/>
    
    0 讨论(0)
  • 2020-12-21 05:33

    Is it possible to remove xml attributes from XSLT AND work with the resulting transform?

    Yes, just search for "multi-pass transformation" and you'll find many answers with good code examples.

    However, for what you want to do such transformation chaining is overly complex and completely unnecessary.

    Just use:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:x="abc123" >
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="x:page">
      <xsl:value-of select="@id"/>
     </xsl:template>
    </xsl:stylesheet>
    

    And in case the default namespace of the XML document isn't known in advance, you can still produce the wanted results in a single pass:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="*[name()='page']">
      <xsl:value-of select="@id"/>
     </xsl:template>
    </xsl:stylesheet>
    
    0 讨论(0)
  • 2020-12-21 05:34

    Many transformations are best split into a pipeline where each stage of the pipeline performs one simple task.

    You can do a multi-stage transformation within a single stylesheet (by holding the results in variables, especially with XSLT 2.0), or you can do it using multiple stylesheets. You can control a pipeline involving multiple stylesheets with a variety of technologies (XProc, Coccoon, Orbeon, Ant, xmlsh) or from your own Java/C# code. Using multiple stylesheets has the advantage that the components of the pipeline are highly reusable.

    0 讨论(0)
提交回复
热议问题