Subject: Re: [xsl] Q: XSLT 1.0 output of namespace From: Hermann Stamm-Wilbrandt <STAMMW@xxxxxxxxxx> Date: Tue, 17 Aug 2010 14:17:45 +0200 |
Lars, thanks for your reply. I only focussed on the distinction between attribute and namespace nodes. I did not test all the testcases -- I should have done. Below you can find a working stylesheet and 6 testcase outputs. > The test above tests the child axis, correct? Yes. > So it is not testing whether the current node is a node/pi/comment/text > node, but whether the current node has such children. Right? Correct, now "self::" is used, see below. > ... more likely the intent was to > test whether the current node is (not) an element or anything else > besides an attribute or a namespace node? Yes. > Also, the above test seems redundant, since anything matched by > "processing-instruction()|comment()|text()" will also be matched by > "node()". Correct. In getting the whole solution to work some other issues arose. The first was that "node()" predicate is true for all 6 different types: comment, processing-instruction, text, element, attribute and namespace. Then I realized the the really difficult part was to differentiate between element, attribute and namespace! (the worst being the empty element) In getting to the solution below I found that ". = ../namespace::*[name()]" as "is-namespace()" test is even simpler than Michael's "count(. | ../@*) != count(../@*)". Similarly ". = ../attribute::*[name()]" can be used as "is-attribute()". So my first shot for "is-element()" (after ruling out text, pi and comment) was this: "not(. = ../attribute::*[name()] | ../namespace::*[name()])" But this was incorrect for a default namespace declaration! Just adding "name() and ..." fixed this issue. Find below a sample XML file, and the stylesheet "dynxp.xsl". As you can see you can pass any XPath statement via --stringparam. This XPath expression is evaluated by dyn:evaluate() just for demonstration and testing purposes. Each result gets output separately and in a readable way. Just in case email scrambles below listings find dynxp.xsl here [1]. (xpath++ tool [2] does similar stuff) $ cat d.xml <?some-PI testing?> <a> <!-- comment1 --> <b n1="urn:a1" xmlns:n1="urn:n1"/> <c>text1<d a2="a2" xmlns="urn:d"/></c> </a> $ xsltproc --stringparam xpathpar "//comment()" dynxp.xsl d.xml ------------------------------------------------------------------------------- <!-- comment1 --> $ xsltproc --stringparam xpathpar "//processing-instruction()" dynxp.xsl d.xml ------------------------------------------------------------------------------- <?some-PI testing?> $ xsltproc --stringparam xpathpar "/a/c/text()" dynxp.xsl d.xml ------------------------------------------------------------------------------- text1 $ xsltproc --stringparam xpathpar "/a/b" dynxp.xsl d.xml ------------------------------------------------------------------------------- <b xmlns:n1="urn:n1" n1="urn:a1"/> $ xsltproc --stringparam xpathpar "/a/c/*/namespace::*" dynxp.xsl d.xml ------------------------------------------------------------------------------- xmlns:xml="http://www.w3.org/XML/1998/namespace" ------------------------------------------------------------------------------- xmlns="urn:d" $ xsltproc --stringparam xpathpar "//attribute::*" dynxp.xsl d.xml ------------------------------------------------------------------------------- n1="urn:a1" ------------------------------------------------------------------------------- a2="a2" $ $ cat dynxp.xsl <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dyn="http://exslt.org/dynamic" > <xsl:output omit-xml-declaration="yes"/> <xsl:param name="xpathpar" select="'//*'" /> <xsl:template match="/"> <xsl:for-each select="dyn:evaluate($xpathpar)"> <xsl:call-template name="doOutput"/> </xsl:for-each> </xsl:template> <xsl:template name="doOutput"> <xsl:text> ------------------------------------------------------------------------------- </xsl:text> <xsl:choose> <xsl:when test="self::comment() | self::processing-instruction() | self::text()"> <xsl:copy-of select="."/> </xsl:when> <xsl:when test="name() and not(. = ../attribute::*[name()] | ../namespace::*[name()])"> <xsl:copy-of select="."/> </xsl:when> <xsl:otherwise> <xsl:if test="not(. = ../attribute::*[name()])"> <xsl:text>xmlns</xsl:text> <xsl:if test="name()">:</xsl:if> </xsl:if> <xsl:value-of select="name()"/> <xsl:text>="</xsl:text> <xsl:value-of select="string()"/> <xsl:text>"</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> $ [1] http://stamm-wilbrandt.de/en/xsl-list/dynxp.xsl [2] https://www.ibm.com/developerworks/forums/thread.jspa?messageID=14455521� Mit besten Gruessen / Best wishes, Hermann Stamm-Wilbrandt Developer, XML Compiler, L3 WebSphere DataPower SOA Appliances ---------------------------------------------------------------------- IBM Deutschland Research & Development GmbH Vorsitzender des Aufsichtsrats: Martin Jetter Geschaeftsfuehrung: Dirk Wittkopp Sitz der Gesellschaft: Boeblingen Registergericht: Amtsgericht Stuttgart, HRB 243294 From: Lars Huttar <lars_huttar@xxxxxxx> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Cc: Hermann Stamm-Wilbrandt/Germany/IBM@IBMDE Date: 08/16/2010 06:08 PM Subject: Re: [xsl] Q: XSLT 1.0 output of namespace On 8/16/2010 7:35 AM, Hermann Stamm-Wilbrandt wrote: > Hello, > > this is a pure XSLT 1.0 question. > > Below template does the (readable) output of the current node even for > attribute and namespace nodes. > In the spec the following is stated: > "There is no pattern that can match a namespace node, ...". > > So I tried it with negative matches for node, pi, comment and text. > But now the differentiation between namespace node and attribute node > ( for output of xnlns:ns1="..." / xmlns="..." / attr="..." ) > seems a bit complex to me. > > Can this be simplified? > > > <xsl:template match="@*"> > attribute > </xsl:template> > > <xsl:template name="doOutput"> > <xsl:choose> > <!-- attribute could be matched, namespace not - handle both --> > <xsl:when test="not(node()|processing-instruction()|comment()|text > ())"> > A question for my own edification.... The test above tests the child axis, correct? So it is not testing whether the current node is a node/pi/comment/text node, but whether the current node has such children. Right? So an empty element would pass this not() test; in other words, an empty element would be treated the same as an attribute or a namespace node. It seems like that is not the intent... more likely the intent was to test whether the current node is (not) an element or anything else besides an attribute or a namespace node? Also, the above test seems redundant, since anything matched by "processing-instruction()|comment()|text()" will also be matched by "node()". I'm not saying this to be critical, but because I believe the OP is a smart guy, and this area is a confusing one for me, I want to check my own comprehension. Thanks, Lars
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Q: XSLT 1.0 output of nam, Martin Honnen | Thread | Re: [xsl] Q: XSLT 1.0 output of nam, Michael Kay |
Re: [xsl] Q: XSLT 1.0 output of nam, Martin Honnen | Date | [xsl] problem with xsl:import and n, Jostein Austvik Jaco |
Month |