Find immediate siblings with criteria related to context element - xpath

I have XML-structure. Context of executing XPath is one of the elements with class attribute "ac". Help me to compose XPath to find all immediate siblings of context element with attribute class "ac1". E.g. if context of execution is the second element with class attribute "ac", the result should contain two (not three) immediate elements with class attribute "ac1".
Thank you.
<container>
<item class="ac"/>
<item class="ac1"/>
<item class="ac1"/>
<item class="ac1"/>
<item class="ac"/>
<item class="ac1"/>
<item class="ac1"/>
<item class="ac2"/>
<item class="ac1"/>
<item class="ac"/>
<item class="ac1"/>
<item class="ac1"/>
<item class="ac1"/>
</container>

I. In XPath 1.0 use the Kayessian method for the intersection of two node-sets:
$ns1[count(.|$ns2) = count($ns2)]
This selects the intersection of the two node-sets $ns1 and $ns2.
Substitute in this :
$ns1 with:
/*/*[#class='ac'][1]/following-sibling::*[#class='ac1']
and $ns2 with:
/*/*[#class='ac'][2]
/following-sibling::*[not(#class='ac1')][3]
/preceding-sibling::*
The resulting XPath expression is:
/*/*[#class='ac'][4]
/following-sibling::*[#class='ac1']
[count(.
|
/*/*[#class='ac'][5]
/following-sibling::*[not(#class='ac1')][6]
/preceding-sibling::*
)
=
count(/*/*[#class='ac'][7]
/following-sibling::*[not(#class='ac1')][8]
/preceding-sibling::*
)
]
XSLT - based verification:
<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="ns1" select=
"/*/*[#class='ac'][9]/following-sibling::*[#class='ac1']"/>
<xsl:variable name="ns2" select=
"/*/*[#class='ac'][10]
/following-sibling::*[not(#class='ac1')][11]
/preceding-sibling::*"/>
<xsl:template match="/">
<xsl:copy-of select=
"$ns1[count(.|$ns2) = count($ns2)]"/>
=========
<xsl:copy-of select=
"/*/*[#class='ac'][12]
/following-sibling::*[#class='ac1']
[count(.
|
/*/*[#class='ac'][13]
/following-sibling::*[not(#class='ac1')][14]
/preceding-sibling::*
)
=
count(/*/*[#class='ac'][15]
/following-sibling::*[not(#class='ac1')][16]
/preceding-sibling::*
)
]
"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<container>
<item class="ac"/>
<item class="ac1"/>
<item class="ac1"/>
<item class="ac1"/>
<item class="ac"/>
<item class="ac1"/>
<item class="ac1"/>
<item class="ac2"/>
<item class="ac1"/>
<item class="ac"/>
<item class="ac1"/>
<item class="ac1"/>
<item class="ac1"/>
</container>
the two XPath expressions (one with variables and the other with the variables substituted) are evaluated and the selected nodes by each of them are copied to the output:
<item class="ac1"/>
<item class="ac1"/>
=========
<item class="ac1"/>
<item class="ac1"/>
II. XPath 2.0 Solution:
Simply use the standard XPath 2.0 intersect operator with the same two node-sets.
Alternatively one can use the standard operators << and >>.

Related

Set required for Tax/VAT field for a specific store in magento 2

I have a magento store with different store view. I want to show Tax/Vat field on checkout but it will mandatory for Italy only.
What i have done:
After selection store view, from customer->customer configuration i have set Show VAT number on Storefront YES
and Show VAT Number set Required.
In checkout page VAT field is showing but required validation not working.
I have tried overwrite with jQuery but didnt succeed. I guess adding attribute in knockjs might be a option but i am really dont know. Can any one help me out. I am stuck.
magento version 2.2.5
I got an alternative solution.
update checkout_index_index.xml
Check closely this line for vat_id <item name="required-entry" xsi:type="boolean">true</item>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shipping-step" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shippingAddress" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shipping-address-fieldset" xsi:type="array">
<item name="children" xsi:type="array">
<item name="vat_id" xsi:type="array">
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
It works for me.
NB: But i am sure most of the cases set VAT ID required at checkout it should be done configuring from admin.

Xslt : rewrite tree to sort child attribute in different parents before exploit data

I'm stumbling on a step of what i want to do :
What i have :
<cat>
<cat2>
<item name="ddd">...</item>
</cat2>
<cat3>
<cat4>
<cat5>
<item name="aaa">...</item>
<item name="fff">...</item>
</cat5>
<item name="bbb">...</item>
</cat4>
<item name="eee">...</item>
</cat3>
<item name="ccc">...</item>
</cat>
And i would like to sort it by name of item (to be exported), so with all "cat" rewrited for the sort, such :
<cat>
<cat3>
<cat4>
<cat5>
<item name="aaa">...</item>
</cat5>
<item name="bbb">...</item>
</cat4>
</cat3>
<item name="ccc">...</item>
<cat2>
<item name="ddd">...</item>
</cat2>
<cat3>
<item name="eee">...</item>
<cat4>
<cat5>
<item name="fff">...</item>
</cat5>
</cat4>
</cat3>
</cat>
I don't care if result is long, because I will export it in (...| itemName|cat|cat1|cat2|...) But I have to keep parents for each, and get them order by name, because sort after exported is quite impossible.
XSLT 3 has a snapshot function that allows you to easily create a copy of a node and its ancestors so using XSLT 3 (as available in the open source version Saxon 9.8 HE for .NET and Java and C/C++) you could at least easily order the item elements by name and then recreate the ancestor hierarchy for each item separately:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:variable name="sorted-items" as="element(item)*">
<xsl:perform-sort select="descendant::item">
<xsl:sort select="#name"/>
</xsl:perform-sort>
</xsl:variable>
<xsl:sequence select="$sorted-items!root(snapshot())"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The result for your sample then is
<cat>
<cat>
<cat3>
<cat4>
<cat5>
<item name="aaa">...</item>
</cat5>
</cat4>
</cat3>
</cat>
<cat>
<cat3>
<cat4>
<item name="bbb">...</item>
</cat4>
</cat3>
</cat>
<cat>
<item name="ccc">...</item>
</cat>
<cat>
<cat2>
<item name="ddd">...</item>
</cat2>
</cat>
<cat>
<cat3>
<item name="eee">...</item>
</cat3>
</cat>
<cat>
<cat3>
<cat4>
<cat5>
<item name="fff">...</item>
</cat5>
</cat4>
</cat3>
</cat>
</cat>
which might suffice if your export only needs the ancestors of each item and preserving the sibling structure does not matter.
Online sample is at https://xsltfiddle.liberty-development.net/bFDb2C2.

magento ui component multiselect xml

I can not understand why the error
Could not save the brand: Notice: Array to string conversion in C:\OpenServer\domains\localhost\2016\mercury_61189_222_007\vendor\magento\zendframework1\library\Zend\Db\Statement\Pdo.php on line 228
on the idea of all done right, here is the code of the module
<field name="website_id_2">
<argument name="data" xsi:type="array">
<item name="options" xsi:type="object">Magento\Store\Model\ResourceModel\Website\Collection</item>
<item name="config" xsi:type="array">
<item name="dataType" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">Website 2</item>
<item name="formElement" xsi:type="string">multiselect</item>
<item name="source" xsi:type="string">page</item>
<item name="dataScope" xsi:type="string">website_id_2</item>
<item name="validation" xsi:type="array">
<item name="required-entry" xsi:type="boolean">true</item>
</item>
</item>
</argument>
</field>
Can someone know the nuances?
I decided my question.
It was necessary for the save function to execute () to write 2 lines to preserve the array
$data['website_id_2']=implode(',',$data['website_id_2']);
$model->setData($data)->setId($this->getRequest()->getParam('id'));

Magento 2 issue on header minicart

Im having problem on integrating header mini cart into my custom theme. Below are the screenshots of the issue. Any help is much appreciated. Thanks in advance :)
Screenshots:
Below is the default.xml code.
<referenceContainer name="header.container">
<container name="header-wrapper" label="Page Header" as="header-wrapper" htmlTag="div" htmlClass="top-header">
<!-- top links with cart -->
<container name="topcartoptions" label="Top Cart Options" htmlTag="div" htmlClass="top-cart-options text-right" before="-">
<block class="Magento\Cms\Block\Block" name="block-top-links">
<arguments>
<argument name="block_id" xsi:type="string">block-top-links</argument>
</arguments>
</block>
</container>
<!-- top menu -->
<container name="mainnavigation" label="Main Navigation" htmlTag="div" htmlClass="main-navigation" after="topcartoptions">
<container name="main-navigation-container" label="Main Navigation" htmlTag="div" htmlClass="container">
<container name="main-navigation-container-row" label="Main Navigation" htmlTag="div" htmlClass="row">
<container name="main-nav-row-bootstrap-class" htmlTag="div" htmlClass="col-lg-12 col-md-12 col-sm-12 col-xs-12 text-center">
<block class="Magento\Cms\Block\Block" name="block-main-nav">
<arguments>
<argument name="block_id" xsi:type="string">block-main-nav</argument>
</arguments>
</block>
</container>
</container>
</container>
</container>
<block class="Magento\Checkout\Block\Cart\Sidebar" name="minicart" as="minicart" after="logo" template="cart/minicart.phtml">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="types" xsi:type="array"/>
<item name="components" xsi:type="array">
<item name="minicart_content" xsi:type="array">
<item name="component" xsi:type="string">Magento_Checkout/js/view/minicart</item>
<item name="config" xsi:type="array">
<item name="template" xsi:type="string">Magento_Checkout/minicart/content</item>
</item>
<item name="children" xsi:type="array">
<item name="subtotal.container" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="config" xsi:type="array">
<item name="displayArea" xsi:type="string">subtotalContainer</item>
</item>
<item name="children" xsi:type="array">
<item name="subtotal" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="config" xsi:type="array">
<item name="template" xsi:type="string">Magento_Checkout/minicart/subtotal</item>
</item>
</item>
</item>
</item>
<item name="extra_info" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="config" xsi:type="array">
<item name="displayArea" xsi:type="string">extraInfo</item>
</item>
</item>
<item name="promotion" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="config" xsi:type="array">
<item name="displayArea" xsi:type="string">promotion</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
<container name="minicart.addons" label="Mini-cart promotion block"/>
</block>
</container>
</referenceContainer>

Run second grep relative to first find

I need to find a specific string in a text, and then base on the position of the string, find a second string that is the closes to it (backwards) and print the information. I've got the following:
<tile x="143" y="43" z="7">
<item id="2656"/>
<item id="2111" count="5"/>
<item id="2194"/>
<item id="2205"/>
<item id="2400"/>
</tile>
<tile x="143" y="44" z="7">
<item id="2656"/>
<item id="2111" count="5"/>
<item id="2194"/>
<item id="2205"/>
</tile>
<tile x="143" y="45" z="7">
<item id="2656"/>
<item id="2111" count="5"/>
<item id="2194"/>
<item id="2205"/>
</tile>
<tile x="144" y="43" z="7">
<item id="2656"/>
<item id="2194"/>
<item id="2111" count="5"/>
<item id="2506" special_description="something something something (Arm:12) [Test]"/>
<item id="2194"/>
<item id="2216"/>
<item id="2400"/>
</tile>
<tile x="144" y="44" z="7">
<item id="2656"/>
<item id="2111" count="5"/>
<item id="2194"/>
<item id="2418"/>
<item id="2216"/>
<item id="2431"/>
</tile>
<tile x="144" y="45" z="7">
<item id="2656"/>
<item id="2658"/>
<item id="2111" count="5"/>
<item id="2506" special_description="something something (Arm:12) [Whatever]"/>
<item id="2194"/>
<item id="2216"/>
</tile>
<tile x="146" y="43" z="7">
<item id="1738"/>
<item id="1738"/>
<item id="1738"/>
<item id="2160" count="50"/>
<item id="2183"/>
<item id="2127"/>
<item id="2127"/>
<item id="2205"/>
<item id="2506"/>
<item id="2127"/>
</tile>
The text is all one line, I've split it in separate lines for it to be easier to look through. Originally it looks like this:
<tile x="143" y="43" z="7"><item id="2656"/><item id="2111" count="5"/><item id="2194"/><item id="2205"/><item id="2400"/></tile><tile x="143" y="44" z="7">...
Let's say I'm looking for 2 specific item id's - 2506 and 2418. I've found 2506 in the fourth tile block using grep, now I want to see what tile coordinates it has:
I've found this:
<item id="2506" special_description="something something something (Arm:12) [Test]"/>
and right above it I find this:
<tile x="144" y="43" z="7">
How would I be able to extract the tile information for all those, get the special description if it exists and generate a log?
Ideally it would look like this (but the output is not too important as long as I get all the information extracted):
2506:
144,43,7 | [Test]
144,45,7 | [Whatever]
146,43,7 |
2418:
144,44,7 |
Ideally if someone could get me a ready solution, it'd be much appreciated, but just a helpful pointer would be sufficient!
awk to the rescue!
this may get you started...
$ awk -F'\n' -v RS= '/id="2506"/{print $1}' file
<tile x="144" y="43" z="7">
<tile x="144" y="45" z="7">
<tile x="146" y="43" z="7">
It's better to write a script to do this. Here is the pseudo code:
for all lines in file do {
if line =~ /pattern1/ {
match1 = line
}
elsif line =~ /pattern2/ {
echo line, match1
}
}

Resources