2

Possible Duplicate:
Generate/get xpath from XML node java

This is a follow-on question from a previous question I’ve asked, (I’ve decided to ask as a separate question, as the previous seems to be getting too big).

I’ve got the following XSLT, which allows me to transform a specified XML String into a set of XPath expressions:

<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="text()"/>

    <xsl:template match="*[not(*)]">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/',local-name(),'[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="node()"/>
    </xsl:template>

</xsl:stylesheet>

For example, the XML String:

<ns1:create xmlns:ns1='http://predic8.com/wsdl/material/ArticleService/1/'>
    <article xmlns:ns1='http://predic8.com/material/1/'>
        <name />
        <description />
        <price xmlns:ns1='http://predic8.com/common/1/'>
            <amount />
            <currency xmlns:ns1='http://predic8.com/common/1/‘>AUD</currency>
        </price>
        <id xmlns:ns1='http://predic8.com/material/1/‘>1</id>
    </article>
    <article xmlns:ns1='http://predic8.com/material/2/'>
        <name xmlns:ns1='http://predic8.com/material/2/'>some name</name>
        <description xmlns:ns1='http://predic8.com/material/2/'>some description</description>
        <price xmlns:ns1='http://predic8.com/common/2/'>
            <amount xmlns:ns1='http://predic8.com/common/2/'>00.01</amount>
            <currency xmlns:ns1='http://predic8.com/common/2/'>USD</currency>
        </price>
        <id xmlns:ns1='http://predic8.com/material/2/'>2</id>
    </article>
</ns1:create>

Would get transformed into:

/create[1]/article[1]/name[1]
/create[1]/article[1]/description[1]
/create[1]/article[1]/price[1]/amount[1]
/create[1]/article[1]/price[1]/currency[1] , AUD
/create[1]/article[1]/id[1] , 1
/create[1]/article[2]/name[1]
/create[1]/article[2]/description[1]
/create[1]/article[2]/price[1]/amount[1]
/create[1]/article[2]/price[1]/currency[1]
/create[1]/article[2]/id[1]

My question: How, can I modify the XSLT so that I can also select and append the current node’s text value. Noting also that, as I've illustrated in the sample XML file supplied, some nodes may not contain text values, etc.

So for the sample above, I would expect something like (e.g. comma-separated output):

/create[1]/article[1]/name[1] , 
/create[1]/article[1]/description[1] , 
/create[1]/article[1]/price[1]/amount[1] , 
/create[1]/article[1]/price[1]/currency[1] , 
/create[1]/article[1]/id[1] , 
/create[1]/article[2]/name[1] , some name
/create[1]/article[2]/description[1] , some description
/create[1]/article[2]/price[1]/amount[1] , 00.01
/create[1]/article[2]/price[1]/currency[1] , USD
/create[1]/article[2]/id[1] , 2
Community
  • 1
  • 1
Larry
  • 11,439
  • 15
  • 61
  • 84
  • **The answer is provided here**: http://stackoverflow.com/questions/4746299/generate-get-xpath-from-xml-node-java Just use it. I know applications for testing XSLT that use this as the core for tests of any XSLT transformation. – Dimitre Novatchev Jul 19 '12 at 15:28
  • Thanks, that post is quite brilliant... wish I would have known about it earlier! – Larry Jul 19 '12 at 15:41
  • Yes, sure, it certainly looks a robust solution, and solves more of my complete problem (+1). – Larry Jul 19 '12 at 15:56
  • 1
    @Kev♦ Thank you for deleting my answer ... Besides closing the question, you could at least specify which is the duplicate question -- otherwise any interested reader wouldn't know where to look. I hope this is just a casual omission from your side and not a display of pedantic formalism with lack of thought -- which I hope no moderator should ever exhibit. If, unfortunately, this comment is embarassing to you, I'll understand if you delete it. So will the people who have read this comment :) – Dimitre Novatchev Jul 19 '12 at 18:32
  • 2
    @DimitreNovatchev There's a link at the top of the page that goes to the original question. Kev didn't omit anything. – Bill the Lizard Jul 19 '12 at 20:07
  • 1
    @DimitreNovatchev - your accepted answer linked to another question with an accepted answer. That means it's a duplicate, it's standard procedure that we close these questions as dupes and delete such answers as yours. Next time just flag as a duplicate. Thanks. – Kev Jul 19 '12 at 22:39

1 Answers1

0

It should as simple as adding a select=./text() at the appropriate node, or have I missed something subtle in your question?

<xsl:template match="*[not(*)]">
    <xsl:for-each select="ancestor-or-self::*">
        <xsl:value-of select="concat('/',local-name(),'[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
    </xsl:for-each>
    <xsl:text> , </xsl:text>
    <xsl:value-of select="./text()"/>
    <xsl:text>&#xA;</xsl:text>
    <xsl:apply-templates select="node()"/>
</xsl:template>

Output:

/create[1]/article[1]/name[1] , 
/create[1]/article[1]/description[1] , 
/create[1]/article[1]/price[1]/amount[1] , 
/create[1]/article[1]/price[1]/currency[1] , AUD
/create[1]/article[1]/id[1] , 1
/create[1]/article[2]/name[1] , some name
/create[1]/article[2]/description[1] , some description
/create[1]/article[2]/price[1]/amount[1] , 00.01
/create[1]/article[2]/price[1]/currency[1] , USD
/create[1]/article[2]/id[1] , 2
StuartLC
  • 104,537
  • 17
  • 209
  • 285