Jump to content

Martin Honnen

Members
  • Posts

    327
  • Joined

  • Last visited

Everything posted by Martin Honnen

  1. Well my suggestion is not to try to convert line breaks to "br" elements but instead simply put the text with the line breaks into a HTML "pre" element as then the browser will render line breaks as line breaks and will not collapse white space as it happens in other elements like the "p" element.
  2. Well HTML has the "pre" element so write a template that transforms the MessageResponse element into a "pre" element: <xsl:template match="ns5:MessageResponse"> <pre><xsl:value-of select="."/></pre></xsl:template> of course making sure the stylesheet declares xmlns:ns5="https://enroute.com/ctsp/queries/1.0" on the xsl: stylesheet element.Then all you need is to make sure the template is used, the built-in templates should ensure that, if you write your own make sure you use apply-templates e.g. <xsl:template match="/"> <html> <head> <title>Example</title> </head> <body> <xsl:apply-templates/> </body> </html></xsl:template>
  3. If you want to use XSLT 2.0 then the first step translating an XSLT 1.0 stylesheet to XSLT 2.0 is simply changing version="2.0"on the xsl: stylesheet element and then to use an XSLT 2.0 processor. I see no reason why your code moved to version="2.0" <xsl:stylesheet xmlns:wd="urn:com.workday.report/CR-INT034-ADP-Garnishment_Disbursements_File-Outbound2" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="2.0"><xsl:strip-space elements="*"/><xsl:output indent="no" method="text" /><xsl:key name="entry" match="wd:Report_Entry" use="wd:field" /><xsl:template match="wd:Report_Data"><xsl:value-of select="count(wd:Report_Entry [ generate-id() = generate-id(key('entry', wd:field))])"/> </xsl:template></xsl:stylesheet> would cause any problem or any wrong result with an XSLT 2.0 processor. Even if you would not change the version but simply use your XSLT 2.0 processor the result would be the same. But of course using the new XPath and XSLT 2.0 features like the "distinct-values" function usually results in more compact, readable and maintainable code so your later approach is certainly preferable over the key-based XSLT 1.0 approach. There are some issues however where a change of the version attribute to 2.0 and the switch to an XSLT 2.0 processor could give different results (mainly the semantics of xsl: value-of select="some node set" changes to output all nodes in the selected node set while XSLT 1.0 only outputs the first select node in the node set).
  4. Well the xml-stylesheet processing instruction is mainly used by browsers to automatically transform an XML document loaded in a browser window with the referenced stylesheet. On the other hand most browser like Mozilla or IE expect you to transform XML to some format they know to render, e.g. XML to XHTML or to XHTML plus SVG. So if you want to transform XML to XML then trying this inside of the browser is not necessary a good environment to test such transformation. As for how to do XML to XML transformation, assuming you have the input <root> <list> <item>foo</item> <item>bar</item> </list></root> and you want to transform that to XHTML then you simply write templates performing the transformation e.g. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns="http://www.w3.org/1999/xhtml"> <xsl:output indent="yes"/> <xsl:template match="/"> <html xml:lang="en"> <head> <title>Example</title> </head> <body> <h1>Example</h1> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="list"> <ul> <xsl:apply-templates/> </ul> </xsl:template> <xsl:template match="item"> <li> <xsl:apply-templates/> </li> </xsl:template> </xsl:stylesheet> See it online at http://home.arcor.de/martin.honnen/xslt/test2013042501.xml. So whether you want to transform XML to HTML or to XML does not make much of the difference as to how you write stylesheets, you simply write templates matching the nodes in the input XML and you create result elements of the output XML or HTML.
  5. Try any XPath tutorial."." denotes the context node, ".." the parent node.So"./task" selects the "task" child elements of the context node while "../task" selects the "task" child elements of the parent node of the context node.Usually you would simply use "task"instead of "./task"As for ".//task", it is short for "./descendant-or-self::node()/task", see http://www.w3.org/TR/xpath/#path-abbrev for details which says // is short for /descendant-or-self::node()/. For example, //para is short for /descendant-or-self::node()/child::para and so will select any para element in the document (even a para element that is a document element will be selected by //para since the document element node is a child of the root node); div//para is short for div/descendant-or-self::node()/child::para and so will select all para descendants of div children.
  6. Use a positional predicate foo[x] (the first index is 1) e.g. <xsl:template match="/"> <xsl:value-of select="root/foo[3]"/></xsl:template> outputs the string value of the third 'foo' child element of the 'root' element.If you are not looking for a certain child element but for the third 'foo' element in the complete document (where 'foo' elements could exist at different nesting levels) then use <xsl:template match="/"> <xsl:value-of select="(//foo)[3]"/></xsl:template>
  7. Well there are many XML formats with different semantics, the snippet you have posted does not even look like the markup of XML as it has no tags, so it is certainly not possible to tell which XML format you use and which semantics it has. The expression /fasd/Comml[LocRef="ID_1",TypeOf ='Dealer']/amt could be an XPath 2.0 expression however that selects node in an XML document where the root element named "fasd" has child element(s) named "Comml" which have a child element named "LocRef" with the value "ID_1" or/and a child element named "TypeOf" with the value "Dealer" and where finally the expression selects the child elements named "amt" of the "Comml" elements.
  8. You would need to change the Javascript code loading the files, if you want to use XSLT on responseXML with transformNode then with IE 10 you need to make sure you use the MSXML object, so change function loadXMLDoc(dname){if (window.XMLHttpRequest) { xhttp=new XMLHttpRequest(); }else { xhttp=new ActiveXObject("Microsoft.XMLHTTP"); }xhttp.open("GET",dname,false);xhttp.send("");return xhttp.responseXML;} to function loadXMLDoc(dname){ var req; if (typeof ActiveXObject !== 'undefined') { req = new ActiveXObject('Msxml2.XMLHTTP.3.0'); } else if (typeof XMLHttpRequest != 'undefined') { req = new XMLHttpRequest(); } if (req) { req.open('GET', dname, false); req.send(); return req.responseXML; } // else handle case here that browser does not support ActiveXObject nor XMLHttpRequest}
  9. You can pass parameters to templates and you could store the element or names of types in a parameter you pass to the template.
  10. You can write several stylesheets where one transforms the result of another. Or with one stylesheets (and XSLT 2.0), you can apply more than one transformation step by using variables and modes e.g. <xsl:variable name="temp"> <xsl:apply-templates mode="step1"/></xsl:variable> <!-- now write templates for the mode step1 and the XML elements you want to transform --> <xsl:template match="temp2"> <xsl:apply-templates select="$temp1/node()" mode="step2"/></xsl:template> <!-- now here write templates for mode step2 processing the elements created in variable temp and step1 --><xsl:template match="/"> <!-- create final output here --> <xsl:apply-templates select="$temp2/node()"/></xsl:template> In theory you might no need mode if all the different formats use different elements or elements in different namespaces but for clarity I would use them to cleanly separate the processing steps.
  11. Well an XSLT program is an XML document so you need to make sure you write your code following the XML syntax rules. And with XML the ampersand is special, it is used to start a character or entity reference, otherwise it needs to be escaped. So proper XML and XSLT syntax is using && to write two ampersands.
  12. Well you haven't really told us in what way Chrome fails? Have you checked its error console for messages telling you what is wrong? As far as I remember loading from the file system is a problem so you need to make sure you load your XML and XSLT over HTTP. There is however a command line switch to start Chrome with lowered security settings so that a file (like an XML document) can load another file (like its stylesheet) from the file system, see http://peter.sh/experiments/chromium-command-line-switches/ and the switch --allow-file-access-from-files. See also http://www.chromium.org/developers/how-tos/run-chromium-with-flags.
  13. <xsl:variable name="qid" select="substring-before(substring-after(//td[@class = 'tdSearch']/a[@class = 'tdSearchOptions'][1], 'query_id='), '&amp')"/> might do.
  14. Well only XSLT 2.0 has support for date respectively dateTime data types. So using an XSLT 2.0 processor like Saxon 9, AltovaXML or XmlPrime you can use code like <xsl:when test="xs:dateTime($var1) gt xs:dateTime($var2)">...</xsl:when> but the input needs to be in the format defined by the W3C schema language which is yyyy-mm-ddThh:mm:ss (with an optional time zone specification trailing) e.g. 2013-01-11T16:41:00+01:00. If you use an XSLT 1.0 processor then the comparison operators less than and greater than only work for numbers so you would need to ensure the format is yyyymmddhhmmss or you would need to convert any input data to that format in your code.
  15. Assuming you target MSXML 6 in Office you could try to define the mapping table as a global parameter and then use the node-set extension function that MSXML supports to have a node set you can apply XPath on: <xsl:param name="my-table-rtf"> <my:recoding-table font="Symbol"> <my:char code="!" value="21" altvalue="F021" entity="!"/> <!--EXCLAMATION MARK--> <my:char code=""" value="22" altvalue="F022" entity="∀"/> <!--FOR ALL-->...... </my:recoding-table></xsl:param><xsl:variable name="my-table" select="msxsl:node-set($my-table-rtf)" xmlns:msxsl="urn:schemas-microsoft-com:xslt"/>...<xsl:value-of select="substring($my-table/my:recoding-table[@font=$font-family]/my:char[substring(@code, 1, 1)=substring($string, 1, 1)]/@entity, 1, 1)"/>
  16. Well the current version of XSLT and XPath is the version 2.0 so with that version respectively if you use an XSLT 2.0 processor you can do e.g. <xsl:variable name="path">c:\data\xxx\filename.doc</xsl:variable><xsl:variable name="file-name" select="tokenize($path, "\\")[last()]"/> That way the variable "file-name" is of type string with the value "filename.doc".With an XSLT 1.0 processor you will need to check whether an extension like http://www.exslt.org/str/functions/tokenize/index.html is supported or you can make use of callable templates like in http://www.dpawson.co.uk/xsl/sect2/N7240.html#d10127e349.
  17. The implementation of client-side XSLT 1.0 is mature and well done in current browsers (and back to IE 6), only that try it application on the w3schools site is poorly done.
  18. As interesting as a that client-side try XSLT tool might be, its implementation is rather poor so the behaviour that you see is simply a shortcoming in the implementation; it takes the source code entered in the two textareas and inserts it in other textareas hidden in an iframe to then parse the textarea contents as XML with client-side Javascript. That way the proper escaping of '<' is unescaped by the browser when Javascript accesses the value pulled from the textarea and the XML parser correctly indicates an XML syntax error. You can encounter the same problem if you use a '&lt' in the XML input source sample. If you want to learn XSLT I would suggest to install an XSLT processor like Saxon 9 or AltovaXML with a command line interface and simply edit the files in a text editor of your choice. Or you might try other online try-it offers like http://xmlplayground.com/index.php (Make sure there you check to checkbox "involve" on the XSLT code sample before hitting the "run" button) but I am not sure they do any better or don't have other shortcomings.
  19. To give you an example, instead of putting all code into one template, your code is easier to read and maintain if you replace stuff like <xsl:for-each select="Arbolgenealogico/Familia/Primos"><tr><td><xsl:value-of select="Nombre"/></td><td><xsl:value-of select="Apellido"/></td><td><xsl:value-of select="Fechanac"/></td><td><xsl:value-of select="Edad"/></td><td><xsl:value-of select="@Rama"/></td></tr></xsl:for-each> by <xsl:apply-templates select="Arbolgenealogico/Familia/Primos"/> and then write a template <xsl:template match="Familia/Primos"> <tr> <td><xsl:value-of select="Nombre"/></td> <td><xsl:value-of select="Apellido"/></td> <td><xsl:value-of select="Fechanac"/></td> <td><xsl:value-of select="Edad"/></td> <td><xsl:value-of select="@Rama"/></td> </tr></xsl:template> You might even go further and use <xsl:template match="Familia/Primos"> <tr> <xsl:apply-templates select="Nombre , Apellido , Fechanac , Edad , @Rama"/> </tr></xsl:template><xsl:template match="Nombre | Apellido | Fechanac | Edad | Primos/@Rama"> <td> <xsl:value-of select="."/> </td></xsl:template> However <xsl:apply-templates select="Nombre , Apellido , Fechanac , Edad , @Rama"/> is only possible with XSLT 2.0 (and XSLT 2.0 processors like Saxon 9 or AltovaXML or XmlPrime), for XSLT 1.0 you could do <xsl:template match="Familia/Primos"> <tr> <xsl:apply-templates select="@Rama | *"/> </tr></xsl:template> but then the order in which columns are output depends on the order of the child elements in the input.If that order is different from the output order you want then with XSLT 1.0 you need to spell out the order with <xsl:template match="Familia/Primos"> <tr> <xsl:apply-templates select="Nombre"/> <xsl:apply-templates select="Apellido"/> <xsl:apply-templates select="Fechanac"/> <xsl:apply-templates select="Edad"/> <xsl:apply-templates select="@Rama"/> </tr></xsl:template>
  20. XSLT 1.0 is not good at such tasks, consider to use XSLT 2.0 and xsl:analyze-string. If you really want to use it with XSLT 1.0 then you I put together http://home.arcor.de/martin.honnen/xslt/test2012062803.xml, works for me with Firefox and Opera, with IE 9 I get unwanted white space inserted, I don't have time to debug that. Stylesheet is at http://home.arcor.de/martin.honnen/xslt/test2012062803.xsl, uses a file mapping characters to colors at http://home.arcor.de/martin.honnen/xslt/test2012062804.xml. And the solution is rather inefficient as it processes the contents of each text node character by character. And recursive template might run out of stack space if the XSLT processor does not implement tail recursion.
  21. I am not sure I understand what you want to achieve. If the 'para' element is the context node and you want to access the first child element then using the path '*[1]' suffices, then any preceding text node sibling is '*[1]/preceding-sibling::text()'.
  22. Which version of XSLT do you use or want to use? XSLT 2.0 has better string processing and replacement than XSLT 1.0.And what exactly does "replace with background color" mean? If the input XML (or HTML?) is <p>For the first three decades[color=#ff0000]⁴[/color] of the history<sup>3</sup> ...</p> , how should the result look you want to create with XSLT?
  23. You haven't told us which XSLT processor you use, assuming an XSLT 2.0 processor like Saxon 9, AltovaXML or XmlPrime you should be able to use your code against the input sample you have shown by doing e.g. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xpath-default-namespace="http://www.callassoftware.com/ns/pdftoolbox/1.0"> <xsl:template match="/metadatareport"> <fieldlist> <field> ... <value><xsl:value-of select="documents/document/metadata/metadatavalue[@property_id='xmpMM:TV_SONumber']"/></value> ... </field> </fieldlist></xsl:template> </xsl:stylesheet> With an XSLT 1.0 processor you need to do e.g. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:df="http://www.callassoftware.com/ns/pdftoolbox/1.0" exclude-result-prefixes="df"> <xsl:template match="/df:metadatareport"> <fieldlist> <field> ... <value><xsl:value-of select="df:documents/df:document/df:metadata/df:metadatavalue[@property_id='xmpMM:TV_SONumber']"/></value> ... </field> </fieldlist></xsl:template> </xsl:stylesheet> That should give you an idea how to handle the namespace in the input with the respective XSLT versions.
  24. Which XSLT processor do you use?Are you sure you get the result you have posted with the samples you have posted? I could explain why the value-of expressions don't select anything, that is due to a namespace being used in the XML input, on the other hand with that the match="/metadatareport" shouldn't work either. As for fixing it, with XSLT 2.0 and an XSLT 2.0 processor using xpath-default-namespace="http://www.callassoftware.com/ns/pdftoolbox/1.0" on the xsl:stylesheet could help, as long as the input is as posted. If the root element is not in a namespace it might get more complex.
  25. You need <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@ | node()"/> </xsl:copy></xsl:template> as the base template for all such task, it is the so called "identity transformation" that copies nodes level by level. Now you can add templates for those nodes you want to modify e.g. <xsl:template match="CAEXFile/InstanceHierarchy/InternalElement/InternalElement"> <xsl:copy> <xsl:attribute name="FurtherInformation">ConstantValue</xsl:attribute> <xsl:apply-templates select="@* | node()"/> </xsl:copy></xsl:template>
×
×
  • Create New...