XSLT - how to match any non-text node children? - xslt

I'm new to XSLT and I can't figure out how to get an xsl:if that matches when there are no child tags.
I want this to match:
<context>
howdy
</context>
And this not:
<context>
<child>
howdy
</child>
</context>

the relevant xpath expression should look like:
//context[not(./*)]

You could also specify count(child::*) = 0 .

Related

How to get the next node's child value inside a for-loop in XSLT

I am trying to access a value from the next node inside a for loop in XSLT.
The XML source is :
<?xml version="1.0" encoding="UTF-8"?>
<tree>
<parent>
<id>1</id>
<child>
<effective_date>01-09-2019</effective_date>
<hours>10</hours>
<dept>1</dept>
</child>
<child>
<effective_date>01-10-2019</effective_date>
<hours>20</hours>
<dept>1</dept>
</child>
<child>
<effective_date>01-10-2019</effective_date>
<class>A</class>
</child>
</parent>
<parent>
<id>2</id>
<child>
...
</child>
<child>
..
</child>
</parent>
</tree>
The desired output is that I want the next child node's Effective_date value in first validUntil tag in result like below :
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<departments>
<department>
<code>1</code>
<weeklyHours>10</weeklyHours>
<validFrom>2019-09-09</validFrom>
<validUntil>2019-10-01</validUntil
</department>
<department>
<code>1</code>
<weeklyHours>20</weeklyHours>
<validFrom>2019-10-01</validFrom>
<validUntil/>
</department>
</departments>
</employees>
In my original xslt, I am inside a for loop, which I am entering conditionally based on whether a child element has change in hours or not. So this has to be accessed inside a for loop.
If the xsl:for-each is iterating over sibling elements, then you can get the next element using following-sibling::*
If you are iterating over an arbitrary sequence $SEQ, then you can get the next element using:
XSLT 2.0: subsequence($SEQ, position()+1, 1)
XSLT 1.0: <xsl:variable name="p" select="position()"/><xsl:.... select="$SEQ[$p+1]"/>
Don't make the mistake of using $SEQ[position()+1] - the value of position() changes within a predicate.

Providing xml data in Django template

I have a form that make xml request, after that i recieve xml respond
that look like this:
<root>
<item>
<id>1</id>
<name>name</name>
<description>description</description>
</item>
<item>
<id>2</id>
<name>name</name>
<description>description</description>
</item>
</root>
Now I want to put this data in to the table and render it in to template. Further I want use separate element. For example user have to choose one of these elements and make order. As I understand to do this, i should parse this data using some library for example lxml, then covert it to the dictionary and than render to template, am i right or there is other way to do this? Thanks a lot.

Regex match tag with no spaces

I've the below html tags.
<item id="ID1" num="num1">
<item id="ID1">
I want a regex to match <item id="ID1"> and ignore <item id="ID1" num="num1">.
please let me know how can i do this.
Thanks
I'd use:
/<item id="[^"]+">
You can use \S+ to match any non-space characters.
<item id=\S+>
Try:
<item id=\"[^ ]*\">
/<item id=".*?"\s*>
You can try this.

Finding unique nodes with xslt inside a for-each

Source XML:
<r:root xmlns:r="http://root/">
<p:parent xmlns:p="http://parent/">
<p:name>John</name>
<p:age>30</age>
<c:child xmlns:c="http://child/">
<c:cname>John_child_1</cname>
<c:cage/>
<c:ItemNumber>1</ItemNumber>
</child>
<c:child xmlns:c="http://child/">
<c:cname>John_child_2</cname>
<c:cage/>
<c:ItemNumber>2</ItemNumber>
</child>
<c:child xmlns:c="http://child/">
<c:cname>John_child_3</cname>
<c:cage/>
<c:ItemNumber>1</ItemNumber>
</child>
</parent>
<p:parent>
<p:name>Doe</name>
<p:age>40</age>
<c:child xmlns:c="http://child/">
<c:cname>Doe_child_1</cname>
<c:cage/>
<c:ItemNumber>2</ItemNumber>
</child>
<c:child xmlns:c="http://child/">
<c:cname>Doe_child_2</cname>
<c:cage/>
<c:ItemNumber>2</ItemNumber>
</child>
</parent>
...
...
...
Target XML:
<root>
<f:father xmlns:f="http://father/">
<f:name>John</name>
<f:age>30</age>
<f:UniqueItemNumber>1</UniqueItemNumber>
<c:child xmlns:c="http://child/">
<c:cname>John_child_1</cname>
<c:cage/>
<c:ItemNumber>1</ItemNumber>
</child>
<c:child xmlns:c="http://child/">
<c:cname>John_child_3</cname>
<c:cage/>
<c:ItemNumber>1</ItemNumber>
</child>
</father>
<f:father xmlns:f="http://father/">
<f:name>John</name>
<f:age>30</age>
<f:UniqueItemNumber>2</UniqueItemNumber>
<c:child xmlns:c="http://child/">
<c:cname>John_child_2</cname>
<c:cage/>
<c:ItemNumber>2</ItemNumber>
</child>
</father>
<f:father xmlns:f="http://father/">
<f:name>Doe</name>
<f:age>40</age>
<f:UniqueItemNumber>2</UniqueItemNumber>
<c:child xmlns:c="http://child/">
<c:cname>Doe_child_1</cname>
<c:cage/>
<c:ItemNumber>2</ItemNumber>
</child>
<c:child xmlns:c="http://child/">
<c:cname>Doe_child_2</cname>
<c:cage/>
<c:ItemNumber>2</ItemNumber>
</child>
</father>
....
...
I have a source xml, which I want to convert to the shown Target xml using XSLT.
In source, we can have more than 1 parent elements, each containing multiple child. To generate the target, first we should find the distinct list of ItemNumber of all childs for each parent. Hence, the Father element in the target xml should be mapped for each unique ItemNumber in the source xml. You can say that it's like group-by clause of sql, where we are grouping on ItemNumber for each Parent. I hope that the example explains the situation.
I have been trying all sorts of thing but haven't reached even near to the solution. I am running into multiple issues while forming a solution:
1. I don't think that I can apply "Muenchian Method" since, I need to find unique ItemNumber for each Parent. Hence, the key has to be defined inside the for-each(parent) element. I am confused here.
2. I think, I should be having a top level for-each(Parent). Inside it, a way to determine unique ItemNumber. And then, when I try to use to get Parent Name, I get nothing because the xpath (/name) isn;t valid when the control is inside the second for-each(uniqueItemNumber). It's tough to explain the problem.
I am hoping that I can get a solution here. Thanks in advance.
You can use Muenchian grouping to group within an element like this, the trick is to include something unique to each parent element as part of the grouping key. Its generate-id() is usually a good candidate.
<xsl:key name="childrenByNumber "match="c:child"
use="concat(generate-id(..), '+', c:ItemNumber)"/>
When you want to extract the groups within a parent you construct the lookup key in the same way:
<xsl:template match="p:parent">
<xsl:variable name="p" select="."/>
<xsl:for-each select="c:child[generate-id() =
generate-id(key('childrenByNumber', concat(generate-id($p), '+', c:ItemNumber))[1])]">
<f:father xmlns:f="http://father/">
<f:name><xsl:value-of select="$p/p:name"/></f:name>
<f:age><xsl:value-of select="$p/p:age"/></f:age>
<f:uniqueItemNumber>
<xsl:value-of select="c:ItemNumber"/>
</f:uniqueItemNumber>
<xsl:copy-of select="key('childrenByNumber', concat(generate-id($p), '+', c:ItemNumber))"/>
</f:father>
</xsl:for-each>
</xsl:template>

Creating custom magento webservices

I'm having some trouble creating some custom web services in Magento. I'm trying to get the module configured properly and I can't seem to make the web services I've defined in the api.xml file show up under the user role setup in the admin area.
I've defined a custom module in app/etc shown here
ctp_GiftCards.xml:
<?xml version="1.0"?>
<config>
<modules>
<ctp_GiftCards>
<active>true</active>
<codePool>local</codePool>
</ctp_GiftCards>
</modules>
</config>
The module code is located in app/local/ctp/GiftCards/
Here is an example of the etc/api.xml:
<?xml version="1.0"?>
<config>
<api>
<resources>
<GiftCards translate="title" module="ctp_GiftCards">
<title>GiftCard webservices</title>
<acl>GiftCards/GiftCard</acl>
<methods>
<update translate="title" module="ctp_GiftCards">
<title>updates a giftcard account</title>
</update>
</methods>
<faults module="ctp_GiftCards">
<invalid_data>
<code>100</code>
<message>giftcard data invalid</message>
</invalid_data>
<card_pool_error>
<code>101</code>
<message>card pool for entry not updated</message>
</card_pool_error>
<cache_error>
<code>102</code>
<message>cache not reset</message>
</cache_error>
</faults>
</GiftCards>
</resources>
<acl>
<resources>
<GiftCards translate="title" module="ctp_GiftCards">
<title>GiftCards</title>
<sort_order>6</sort_order>
<GiftCard translate="title" module="ctp_GiftCards">
<title>GiftCard</title>
<update translate="title" module="ctp_GiftCards">
<title>Update</title>
</update>
</GiftCard>
</GiftCards>
</resources>
</acl>
</api>
</config>
and the etc/config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<ctp_GiftCards>
<version>0.1.0</version>
</ctp_GiftCards>
</modules>
<global>
<models>
<GiftCard>
<class>CTP_GiftCards_Model</class>
</GiftCard>
</models>
</global>
</config>
Any help would be much appreciated.
--edit--
I'm using mangeto pro 1.10
Don't use capital letter (GiftCards) in the name of xml tag inside the node. Moreover, your module's name contains both underscope (_) and capital letter (ctp_GiftCards) which will lead Magento to misunderstand.