How can I replace special characters and spaces in an attribute? I tried various regular expressions but none of them worked as aspected.
<pattern id="setElementId">
<rule context="*[contains(#class, ' domain/element ') and boolean(#id)]">
<!-- Works, replaces 'a' -->
<let name="reqId" value="replace(#id, '[a]', '')"/>
<assert test="#id=$reqId" sqf:fix="setId">
The attribute "id" must comply with the given rules: "<value-of select="$reqId"/>"
</assert>
<sqf:fix id="setId">
<sqf:description>
<sqf:title>Set "id" to "<value-of select="$reqId"/>"</sqf:title>
<sqf:p>Set "id" to the calculated value.</sqf:p>
</sqf:description>
<sqf:replace match="#id" node-type="attribute" target="id" select="$reqId"/>
</sqf:fix>
</rule>
</pattern>
Your last efforts weren't remorsed I think.
Check the CSS codings:
Style {template.css}
Remove that from the end user's example and you'll have your answer!
<sqf:replace match="#id" node-type="attribute" target="id" select="$reqId"/>
</sqf:fix>
That didn't return the side value.
I answer my own question using the suggested replace statement by sergioFC.
<pattern id="setElementId">
<rule context="*[contains(#class, ' topic/dlentry ') and boolean(#id) and descendant-or-self::*[contains(#class, ' ui-d/uicontrol ')]]" role="info">
<let name="reqId" value="descendant-or-self::*[contains(#class, ' ui-d/uicontrol ')]"/>
<let name="reqId" value="replace($reqId, 'ä', 'ae')"/>
<let name="reqId" value="replace($reqId, 'ö', 'oe')"/>
<let name="reqId" value="replace($reqId, 'ü', 'ue')"/>
<let name="reqId" value="replace($reqId, 'Ä', 'ue')"/>
<let name="reqId" value="replace($reqId, 'Ö', 'ue')"/>
<let name="reqId" value="replace($reqId, 'Ü', 'ue')"/>
<let name="reqId" value="replace($reqId, 'ß', 'ss')"/>
<let name="reqId" value="replace($reqId, '[^0-9a-zA-Z]', '')"/>
<assert test="#id=$reqId" sqf:fix="setId" role="warning">
The attribute "id" must comply with the given rules: "<value-of select="$reqId"/>"
</assert>
<sqf:fix id="setId">
<sqf:description>
<sqf:title>Set "id" to "<value-of select="$reqId"/>"</sqf:title>
<sqf:p>Set "id" to the calculated value.</sqf:p>
</sqf:description>
<sqf:replace match="#id" node-type="attribute" target="id" select="$reqId"/>
</sqf:fix>
</rule>
</pattern>
Using this pattern, I can generate id attributes for <dlentry> elements based on the value of the descendant <uicontrol> element.
Related
I'd like to find all instances of the following from within a larger chunk of XML code.
<grouptool id="688" rect="20,576,456,141">
<imagetool id="689" rect="349.15241201716736,581.50668036999,111.22746781115886,132.83658787255914">
<toolstroke WIDTH="1.0" CAP="2" JOIN="2" MITER="0.0" />
<bordercolor />
<image name="head-set-md.png" type="CLIPART" size="20419" w="252" h="300" CRC="3224584205" />
</imagetool>
<rectangletool id="690" rect="20,576,455.0214592274678,141">
<toolstroke />
<toolcolor />
<fillcolor RGB="16777215" ALPHA="0" />
</rectangletool>
<texttool id="691" rect="30,584,214,31">
<toolstroke />
<toolcolor />
<font style="3" size="24" />
<Text>Got Audio Problems?</Text>
</texttool>
<texttool id="692" rect="33,667,266,23">
<toolstroke />
<toolcolor />
<font style="2" size="18" />
<Text>Note: Audio problems can be caused</Text>
</texttool>
<imagetool id="693" rect="36.1785407725322,631.7913669064748,262.9012875536481,24.345323741007192">
<toolstroke WIDTH="1.0" CAP="2" JOIN="2" MITER="0.0" />
<bordercolor />
<image name="unknown.png" type="CLIPART" size="1777" w="260" h="24" CRC="2321804736" />
</imagetool>
<texttool id="694" rect="32,688,269,23">
<toolstroke />
<toolcolor />
<font style="2" size="18" />
<Text>by a weak/spotty internet connection.</Text>
</texttool>
<rectangletool id="695" rect="249.53304721030045,627.7338129496403,30.33476394849785,31.44604316546762">
<toolstroke WIDTH="4.0" />
<toolcolor RGB="52224" />
<fillcolor RGB="16777215" ALPHA="0" />
</rectangletool>
</grouptool>
The key is the rect="20,576,456,141" in the first line. Ultimately, I'll be replacing the contents of the <grouptool> tag with something else, but I only need to do that for the <grouptool> that has the property rect="20,576,456,141".
I'll be using VSCode code for this and have tried a couple things so far that have failed.
Fail #1: <grouptool\b[^>]*?\brect="20,576,456,141"(?:(?!<grouptool\b).)*</grouptool>
Fail #2: <\bgrouptool.*\brect\=\"20\,576\,456\,141\"([\s\S]*?)<\/\bgrouptool>
I hardly know anything about Regex. Please advise if you're able.
In Visual Studio Code, you can search for
(<grouptool(?:\s[^>]*)?\srect="20,576,456,141"[^>]*>)[\w\W]*?(</grouptool>)
and replace with $1New Value$2.
Details:
( - Group 1 ($1):
<grouptool - a fixed string
(?:\s[^>]*)? - an optional occurrence of a whitespace and then zero or more chars other than >
\srect="20,576,456,141" - a whitespace and a rect="20,576,456,141" string
[^>]*> - zero or more chars other than > and then a >
) - end of Group 1
[\w\W]*? - any zero or more chars, as few as possible
(</grouptool>) - Group 2 ($2): a </grouptool> string.
I have an XML file with several entries using same keys and values handling credentials with PowerShell, constructed by Explort-Clixml. An example:
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>System.Collections.Hashtable</T>
<T>System.Object</T>
</TN>
<DCT>
<En>
<S N="Key">fabrikam</S>
<Obj N="Value" RefId="1">
<TN RefId="1">
<T>System.Management.Automation.PSCredential</T>
<T>System.Object</T>
</TN>
<Props>
<S N="UserName">admin#fabrikam.com</S>
<SS N="Password">01000000...</SS>
</Props>
</Obj>
</En>
<En>
<S N="Key">contoso</S>
<Obj N="Value" RefId="2">
<TNRef RefId="1" />
<Props>
<S N="UserName">admin#contoso.com</S>
<SS N="Password">01000000...</SS>
</Props>
</Obj>
</En>
<En>
<S N="Key">adatum</S>
<Obj N="Value" RefId="3">
<TNRef RefId="1" />
<Props>
<S N="UserName">admin#adatum.com</S>
<SS N="Password">01000000...</SS>
</Props>
</Obj>
</En>
</DCT>
</Obj>
</Objs>
The same Export-Clixml handles adding new entries to the list (as hashtables), but I'm struggling when I'd have to modify entries I already have.
1) If I specify to delete an item named contoso, what is the best way to seek, select and remove everything from that <En> entirely?
$xml = [xml](Get-Content file.xml)
$xml.SelectNodes("//Objs/Obj/DCT/En")
... yields nothing at all, whereas
$xml.Objs.Obj.DCT.En.s
works perfect and returns the list of entries by their name. I would need to remove an entire <En> element per given value for <S N="Key">...</S>. Trying to catch the correct entry with
$xml.Objs.Obj.DCT.En.ChildNodes | ? { '#text' -contains 'contoso' }
returns nothing.
2) RefId value in Obj is an auto incremented number. If I remove contoso between the other two entries, what would be the best way to seek and replace the value of RefId in fabrikam and adatum so they're in order (1,2) again? A noteworthy point here is that only the first <En> in the list has sub-elements for <TN RefId> element, the others do not.
If I want to load a document into a variable, I can use
<xsl:variable name="var1" select="document('http://www.mySite.com/file1.xml')" />
=> works, I can use -
<xsl:value-of select="$var1//myNodeName"/>
but now I need to use a URL with parameter.
and the following tests do not work -
<xsl:variable name="var2" select="document('http://www.mySite.com/getfile.cgi?param1=val1¶m2=val2')" />
=> does not work - EntityRef: expecting ';'
<xsl:variable name="var2" select="document('http://www.mySite.com/getfile.cgi?param1=val1¶m2=val2')" />
=> does not work - warn for wrong URL -
http://www.mySite.com/getfile.cgi?param1=val1¶m2=val2:1:
why does it add :1: ???
My Question:
How do I replace the & entity to make the document() function work?
Update:
according to -
http://our.umbraco.org/forum/developers/xslt/5421-Ampersand-in-XSLT
the solution is to store the URL as a variable, then output it disablig output escaping.
e.g.
<xsl:variable name="test" select="http://www.mysite.com/mypage.aspx?param1=1¶m2=2" />
<xsl:value-of select="$test" disable-output-escaping="yes" />
but, how can I apply this solution with document() parameter?
Update 2:
I parse it using PHP -
<?php
Header('Content-type: text/xml');
// http://php.net/manual/en/xsltprocessor.transformtoxml.php
$xml = new DOMDocument;
$xml->load('http://www.mySite.com/devices.xml');
$xsl = new DOMDocument;
$xsl->load('mergedocs.xsl');
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules
echo $proc->transformToXML($xml);
?>
The error I get [note the amp within the URL]:
XML Parsing Error: junk after document element
Location: http://mySite/myPhpFile.php
Line Number 2, Column 1:<b>Warning</b>: XSLTProcessor::transformToXml() [<a href='xsltprocessor.transformtoxml'>xsltprocessor.transformtoxml</a>]:
http://siteIp/cgi-bin/getfile.cgi?p1=v1&p2=v2:1: parser error : Document is empty
in <b>/home/.../myPhpFile.php</b> on line <b>16</b><br />
Encoding the & as & is the correct approach, the URL retrieved by the processor will be the correct one with val1¶m2. I suspect the :1: isn't part of the URL but rather part of the warning message i.e. problem at ::
I have several XML elements like this:
<testcase starttime="2012-09-03 10:41:29" timestamp=" 622.922000">
<testlogfile file="" />
<teststep timestamp=" 622.944000" level="0" type="user" ident="1" result="pass">Do something</teststep>
<teststep timestamp=" 622.965000" level="0" type="user" ident="2" result="pass">Do something</teststep>
<teststep timestamp=" 622.986000" level="0" type="user" ident="3" result="pass">Do something</teststep>
<verdict time="2012-09-03 10:41:30" timestamp=" 623.428000" endtime="2012-09-03 10:41:30" endtimestamp=" 623.428000" result="pass" />
<title>Title goes here</title>
<ident>TC100_06</ident>
<description>description goes here</description>
<extendedinfo type="test case status">Approved</extendedinfo>
<extendedinfo type="traceability">some requirement</extendedinfo>
<extendedinfo type="vehicle mode">Hibernate, Parked, Living, Accessory</extendedinfo>
<extendedinfo type="environment">Station with ATB</extendedinfo>
<extendedinfo type="variants">veh variants</extendedinfo>
</testcase>
I would like to make a xsl:variable select query to count testcases by "ident" and "test case status". I am able to implement 2 separate queries, but I dont know how to join them both:
<xsl:variable name="totalTc" select="count(//testcase[./ident!='text' and ./ident!='obsolete' and ./ident!='rtm' and ./ident!='status overview' and ./ident!='statistics'])"/>
<xsl:variable name="approvedTc" select="count(//extendedinfo[#type='test case status' and text()='Approved'])"/>
I expect joined query should look something like this, but I am unable to query attribute:
<xsl:variable name="totalTc" select="count(//testcase[./ident!='text' and ./ident!='obsolete' and ./ident!='rtm' and ./ident!='status overview' and ./ident!='statistics' and ./extendedinfo=='Approved'])"/>
How about...
<xsl:variable name="totalTc" select="count(
//testcase[
ident!='text' and
ident!='obsolete' and
ident!='rtm' and
ident!='status overview' and
ident!='statistics' and
extendedinfo[
#type='test case status' and
.='Approved']
])"/>
Options
Note in XSLT 2.0, you could instead use:
<xsl:variable name="totalTc" select="count(
//testcase[
not (ident in ('text','obsolete','rtm','status overview','statistics')) and
extendedinfo[#type='test case status' and .='Approved']
])"/>
Also, instead of an expression of the form ...
testcase[ A and B]
... one could instead write....
testcase[A][B]
The former case may be ever so slightly more efficient, but I think personal style should also factor in, in relation to your choice of expression. So for example, one could also put...
<xsl:variable name="totalTc" select="count(//testcase
[not (ident in ('text','obsolete','rtm','status overview','statistics'))]
[extendedinfo[#type='test case status'][.='Approved']])"/>
Use:
count(
//testcase
[extendedinfo[#type='test case status']='Approved'
and
not(teststep
[contains('|text|obsolete|rtm|status overview|statistics',
concat('|',#ident,'|')
)
]
)
]
)
I have in hithighlightedsummary the tag this
<ddd /> Posted: 2/8/2011 10:04 PM <ddd /> Subject: some subject <ddd /> Some Text <ddd />
I would like to get the 'some subject' as a sub string. I have tried using "substring-after(hithighlightedsummary, 'Subject:')", But I don't know how to combine that with the <ddd /> tag.
Did you mean something like this?
substring-after(
//hithighlightedsummary
/text()[
contains(.,'Subject:')
],
'Subject:'
)
Note: I've used an absolute expression because you didn't provide information about context.