Concatenate static string with string that I bring from xml - html

I have <h3>Reflow </h3> and I want bring from xml <xsl:value-of select="Machine/Id"/>
How I can combine those two that the result will be something like <h3>Reflow the value that I brought</h3>
Thanks

Use the standard XPath function concat():
<h3><xsl:value-of select="concat('Reflow ', Machine/Id)"/></h3>

Or more simply:
<h3>Reflow: <xsl:value-of select="Machine/Id"/></h3>

Related

XSL: How to concat additional string when setting a HTML table class

Is there a way to concat some name to a class with a variable?
<table style="display:none;border-style:solid;">
<xsl:attribute name="class">
<xsl:value-of select="BookName"/>
</xsl:attribute>
This piece of my code would name a class by a value of "BookName" from XML, but I need somehow to concat it with just a static text "booktable", meaning that BookName would be some value, but booktable is always static text for example result would be class="NewEncouters2009 booktable"
Simply use
<table style="display:none;border-style:solid;" class="{BookName} booktable">
As for xsl:attribute, you can of course put in any static text there e.g.
<xsl:attribute name="class"><xsl:value-of select="BookName"/> booktable</xsl:attribute>

xslt escape angle brackets

I would like to replace a '.\s+\w+' sequence with a literal
Here is what I have:
<xsl:value-of select="replace($fdesc,'[.][ ]+\w+','<br/>')" />
Here is what I get as an error:
Error on line 33 column 57 of file:/Users/seth/Documents/EmausCCB/XSL/form_list.xsl:
SXXP0003: Error reported by XML parser: The value of attribute "select" associated with an
element type "null" must not contain the '<' character.
Failed to compile stylesheet. 1 error detected.
If I do :
<xsl:value-of select="replace($fdesc,'[.][ ]+\w+','br')" />
I get the expected results
Well if you want to create a br result element you can't use the replace function as it returns a string and not elements.
Use analyze-string instead e.g.
<xsl:analyze-string select="$fesc" regex="[.][ ]+\w+">
<xsl:matching-substring>
<br/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
As for the XML parse error, the right syntax would be <xsl:value-of select="replace($fdesc,'[.][ ]+\w+','<br/>')" />, but that would still return a string and not an element node.

Extract data from html/xml

I'm using Webharvest to retrieve data from websites. It converts the html pages to xml documents before getting for me the wanted data based on the xPath provided.
Now I'm working on a page like this: pastebin Where I showed the blocks I'd like to get. Each block should be returned as a single unit.
the xPath the first element of the block is: //div[#id="layer22"]/b/span[#style="background-color: #FFFF99"]
I tested it and it gives all "bloc start" elements.
the xPath of the last element of the block is: //div[#id="layer22"]/a[contains(.,"Join")]
I tested it and it gives all the "bloc end" elements.
The xPath should return a set of blocks as:
(xPath)[1] = block 1
(xPath)[2] = block 2
....
Thank you in advance
Use (for the first wanted result):
($first)[1] | ($last)[1]
|
($first)[1]/following::node()
[count(.|($last)[1]/preceding::node()) = count(($last)[1]/preceding::node())]
where you need to substitute $first with:
//div[#id="layer22"]/b/span[#style="background-color: #FFFF99"]
and substitute $last with:
//div[#id="layer22"]/a[contains(.,"Join")]
To get the k-th result, substitute in the final expression ($first)[1] with ($first)[{k}] and ($last)[1] with ($last)[{k}], where {k} should be replaced by the number k.
This technique follows directly from the well-known Kayessian formula for set intersection in XPath 1.0:
$ns1[count(.|$ns2) = count($ns2)]
which selects the intersection of the two node-sets $ns1 and $ns2 .
Here is XSLT verification with a simple example:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>03</num>
<num>07</num>
<num>10</num>
</nums>
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="v1" select=
"(//num[. = 3])[1]/following-sibling::*"/>
<xsl:variable name="v2" select=
"(//num[. = 7])[1]/preceding-sibling::*"/>
<xsl:template match="/">
<xsl:copy-of select=
"$v1[count(.|$v2) = count($v2)]"/>
</xsl:template>
</xsl:stylesheet>
applies the XPath expression and the selected nodes are copied to the output:
<num>04</num>
<num>05</num>
<num>06</num>

xsl generate-id() function returns same id twice for different nodes

I have an input xml for a transformation like ;
<?xml version="1.0" encoding="UTF-8" ?>
<AssetcustomerCollection xmlns="http://xmlns.oracle.com/pcbpel/adapter/db/top/somens">
<Assetcustomer xmlns="">
....
</Assetcustomer>
<Assetcustomer xmlns="">
<accountklantid>000000123456789</accountklantid>
<accountrowid>1-W8HQ1J</accountrowid>
<adrestypeaccnt/>
<adrestypecon/>
<assetbankcode>1173</assetbankcode>
<assetnumber>0000001234</assetnumber>
<assetprodcode>1200</assetprodcode>
<assetproduct>Overeenkomst Rekening-courant</assetproduct>
<assetproductlocatie>00</assetproductlocatie>
<assetstatus>Actief</assetstatus>
<assetsubstatus>Lopende rekening</assetsubstatus>
<assettypecode>0010</assettypecode>
<contactklantid/>
<contactrowid/>
<primairaccount>Y</primairaccount>
<primaircontact>N</primaircontact>
<reltypeaccnt>Hoofdcontractant</reltypeaccnt>
<reltypecon/>
<rowidasset>1-X3XBMO</rowidasset>
<rowidassetaccnt>1-X3XBMQ</rowidassetaccnt>
<rowidassetcon/>
<tnsidaccnt/>
<tnsidcon/>
</Assetcustomer>
<Assetcustomer xmlns="">
....
</Assetcustomer>
<Assetcustomer xmlns="">
<accountklantid/>
<accountrowid/>
<adrestypeaccnt/>
<adrestypecon/>
<assetbankcode>1173</assetbankcode>
<assetnumber>0000004321</assetnumber>
<assetprodcode>1201</assetprodcode>
<assetproduct>WereldPas (Zakelijk)</assetproduct>
<assetproductlocatie>00</assetproductlocatie>
<assetstatus>Actief</assetstatus>
<assetsubstatus>Lopende rekening</assetsubstatus>
<assettypecode>0003</assettypecode>
<contactklantid>000000987654321</contactklantid>
<contactrowid>1-X17PLM</contactrowid>
<primairaccount>N</primairaccount>
<primaircontact>Y</primaircontact>
<reltypeaccnt/>
<reltypecon>Pasverantwoordelijke</reltypecon>
<rowidasset>1-X3XBN0</rowidasset>
<rowidassetaccnt/>
<rowidassetcon>1-X3XBNE</rowidassetcon>
<tnsidaccnt/>
<tnsidcon/>
</Assetcustomer>
<Assetcustomer xmlns="">
....
</Assetcustomer>
</AssetcustomerCollection>
When transforming this input xml i got an unexpected output (15 of the 16 input Assetcustomer nodes were transformed) I now have found the cause, but cannot explain why it occurs;
The following transformation returns the same id twice;
<xsl:element name="A">
<xsl:value-of select="generate-id(key('AssetRowIDs',/ns0:AssetcustomerCollection/Assetcustomer[rowidasset = '1-X3XBMO']/*)[1])"/>
</xsl:element>
<xsl:element name="B">
<xsl:value-of select="generate-id(key('AssetRowIDs',/ns0:AssetcustomerCollection/Assetcustomer[rowidasset = '1-X3XBN0']/*)[1])"/>
</xsl:element>
<A>N10211</A>
<B>N10211</B>
While the generated id for any other node with a different rowidasset is different.
Any ideas before i start pulling my hair out ?
Peter
I do not know exactly why , but changing
<xsl:key name="AssetRowIDs" match="Assetcustomer" use="rowidasset"/>
into
<xsl:key name="AssetRowIDs" match="Assetcustomer" use="concat('-',rowidasset,'-')"/>
and
<xsl:for-each select="/ns0:AssetcustomerCollection/Assetcustomer[generate-id() = generate-id(key('AssetRowIDs',rowidasset)[1])]">
into
<xsl:for-each select="/ns0:AssetcustomerCollection/Assetcustomer[generate-id() = generate-id(key('AssetRowIDs',concat('-',rowidasset,'-'))[1])]">
Seems to generate a unique id for each node, still bugging me dat i do not understand the cause of it.
Check the namespace? If the ns0 prefix is bound to a wrong namespace URI, your query will in both cases yield an empty result set. Together with the same first argument for key, that, I imagine, will yield the same call to key() and thus the same ID.
Also I don't think the key() function does what you think it does: http://www.w3schools.com/xsl/func_key.asp
In any case you can apply generate-id() directly on the node set for which you wish to calculate the ID.

Select distinct-values according to child node in XQuery

Let's say I have the following XML:
<info>
<channel>
<A>
<X>
<title>title1</title>
</X>
<Y value="20"/>
</A>
</channel>
<channel>
<A>
<X>
<title>title1</title>
</X>
<Y value="20"/>
</A>
<A>
<X>
<title>title2</title>
</X>
<Y value="20"/>
</A>
</channel>
</info>
and the following XQuery
{
for $A in doc('test.xml')//A
let $TITLE := $A/X/title
where string($A/Y/value) > 20
return
string($TITLE)
}
this, of course, outputs:
title1
title1
title2
How can I use distinct-values in order to remove duplicates? I wonder because for essentially only gives me one item per iteration and I can't call distinct-values on $A. Or is there any other way to remove duplicate output?
The problem is that I need to refer to another node, so basically calling distinct-values(doc...) doesn't work, as it doesn't return nodes.
UPDATE
to filter duplicate nodes, use a variation of the xpath from this answer:
//A[index-of(//A/X/title, X/title)[1]]
this gives you all the As with different titles.
you can expand this xpath expression to also filter on Y - no need for XQuery FLWOR.
UPDATE END
apply the distinct-values to the xpath expression over which you want to iterate:
for $title in distinct-values(doc('test.xml')//A/X/#title)
return string($title)
or just
distinct-values(doc('test.xml')//A/X/#title)