1

I've created an XSLT using an identity template and several templates that match to a potential XPath in the source. However, the matching paths do not always exist. Is there a way to "insert" the path before the matching template applies? Since I know XSLT does not execute procedurally, I wasn't sure how to do this. Examples below.

Let's say this is the XSLT:

<xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

<xsl:template match='pathA'>
   do stuff
</xsl:template>

<xsl:template match='pathB'>
  do something
</xsl:template>

<xsl:template match='pathC'>
   do other stuff
</xsl:template>

And let's say this in the input:

<root>
    <Child>
        <pathA>I have Data!</pathA>
        <pathC>We skipped B!</pathC>
    </Child>
</root>

Is there a way to "create" pathB so that the template that matches the XPath can execute?

Thanks again for any assistance!

Brigand
  • 84,529
  • 20
  • 165
  • 173
J R
  • 49
  • 1
  • 2
  • 7
  • I don't think it's possible without doing two passes with XSLT. You can probably achieve what you're looking for, though: for example, you could process a `pathC` element without a preceding `pathB` sibling differently than a `pathC` element *with* one by adding a template match like this: ` ... `. – Eero Helenius Feb 26 '13 at 08:31
  • That's a good point, I may try that. My only concern is scale. What happens when you have all the way to path AY? Do you then create a different template for all the different permutations? – J R Feb 26 '13 at 15:20
  • Possibly. It depends on what you want to happen when you have all the way to `pathY`. Maybe you want to match all children of `` that don't have a preceding `pathB` sibling? (``) I'd need to know a bit more about exactly what you want to achieve to give more concrete suggestions. Adding a sample of your expected output into your question would help. – Eero Helenius Feb 26 '13 at 16:52
  • that's a good suggestion also. Essentially, "" contains response data from an inquiry. I have the schema for all the **potential** values, but only the items that have values in the table will be populated in the xml response. What I'm trying to do is "update" the data by using match templates. The only problem is when I need to add a value, so the xpath doesn't exists to match to. You can see the original question in this post: http://stackoverflow.com/questions/15079437/selectively-copy-and-update-xml-nodes-using-xslt/15081398#comment21218739_15081398 – J R Mar 01 '13 at 04:18

1 Answers1

1

Good one. How about...

<xsl:template name="pathB">
    <xsl:param name="nodes"/>
    do something 
</xsl:template>


<xsl:template match="Child">
    <xsl:copy>
        <xsl:apply-templates select="@* | pathA[not(../pathB)] | pathB/preceding-sibling::node()"/>
    </xsl:copy>

   <xsl:call-template name="pathB">
       <!-- pass the set of elements of type "pathB", possibly an empty nodeset -->
       <xsl:with-param name="nodes" select="pathB"/>
   </xsl:call-template>

    <xsl:copy>
        <xsl:apply-templates select="node()[not(self::pathA) and not(../pathB)] | pathB/following-sibling::node()"/>
    </xsl:copy>
<xsl:template>
minopret
  • 4,726
  • 21
  • 34
  • hrmm.. would this template still work if pathB isn't available to reference in the source? I tried with a larger source xml I have and it copied everything, but then when I added the "element" tag to build out pathB, it built it first then only copied the text from the source nodes. – J R Feb 26 '13 at 15:18
  • As you see, the intention of my code is no different from the intention of the comment by @EeroHelenius (sorry I'm not good at mentioning people using @ so that may not work). However it may help you to see the additional details that I have included, which in my experience are not in every XSL developer's repertoire. – minopret Feb 26 '13 at 15:39