Have the following input xml which would like to transform to output XML
Input XML:
<O1>
<A1>
<C1>
<CA1/>
</C1>
</A1>
<A2>
<C1>
<C2>
<CA2/>
</C2>
</C1>
</A2>
</O1>
Output XML:
<O1>
<A1>
<C1>
<CA1/>
<status/>
</C1>
<status/>
</A1>
<A2>
<C1>
<C2>
<CA2/>
<status/>
</C2>
<status/>
</C1>
<status/>
</A2>
</O1>
Input and Output structure are exactly same with exception of "status"
Have first done a copy of all nodes from input to output using
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
Have difficulty in adding the status field under each of them now.
Have tried defining another template but didnt succeed
Goal is to add the status element under each "A" and "C"
Assuming that you want to add a <status /> element after each element that starts with the letter C, simply add the following XSLT-1.0 template next to the identity template:
<xsl:template match="*[starts-with(local-name(),'C')]">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
<status />
</xsl:template>
The output is as desired.
Related
I'm stumped and am very new to XSLT. A little direciton would be greatly appreciated. My ultimate objective is to bring the firstName, lastName, and gender elements under the student element up into that element as attributes, but also want to retain the StudentID attribute that already exists there. I'd also like that "year_Collection" to disappear.
I started with this XML document
<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="Upload" Name="Upload">
<student StudentID="123456">
<firstName firstName="John"/>
<lastName lastName="Johnson"/>
<gender gender="M"/>
<year_Collection>
<year value="2013">
<term hoursEarned="18.00" hoursAttempted="18.00" termCode="S1"/>
</year>
</year_Collection>
</student>
</Report>
My desired output looks like this
<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="Upload" Name="Upload">
<student gender="M" lastName="Johnson" firstName="John" StudentID="123456">
<year value="2013">
<term hoursEarned="18.00" hoursAttempted="18.00" termCode="S1"/>
</year>
</student>
</Report>
I was able to use this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:r="Upload" exclude-result-prefixes="r" extension-element-prefixes="r">
<xsl:template match="r:student">
<xsl:copy>
<xsl:for-each select="*">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
To get here:
<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="Upload" Name="Upload">
<student year_Collection="" gender="M" lastName="Johnson" firstName="John">
<year value="2013">
<term hoursEarned="18.00" hoursAttempted="18.00" termCode="S1"/>
</year>
</student>
</Report>
But it overwrites the StudentID attribute that already exists. How do I get the elements to come up as attributes, but not overwrite StudentID?
Also, that pesky year_collection element won't disappear with this, but I can split that into a separate question if that's a better way to go about it.
<xsl:template match="r:year_Collection">
<xsl:apply-templates/>
</xsl:template>
But it overwrites the StudentID attribute that already exists.
No, it doesn't. The problem is you're not copying it. You should start your template with:
<xsl:template match="r:student">
<xsl:copy>
<xsl:copy-of select="#StudentID"/>
or, if you prefer:
<xsl:template match="r:student">
<xsl:copy>
<xsl:copy-of select="#*"/>
to copy any and all attributes the Student has.
Regarding the problem with<year_Collection>, you should try to turn only leaf nodes into attributes, for example:
<xsl:template match="r:student">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:copy-of select="*/#*"/>
<xsl:copy-of select="*/*[#*]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Of course, if your structure is known, naming the required nodes explicitly would be much better, e.g;
<xsl:template match="r:student">
<xsl:copy>
<xsl:copy-of select="#StudentID | r:firstName/#firstName | r:lastName/#lastName | r:gender/#gender"/>
<xsl:copy-of select="r:year_Collection/r:year"/>
</xsl:copy>
</xsl:template>
I have the requirement in which I need to add the new elements. Can anyone please help where I am doing it wrong? I have attached the sample input, sample output and I have attached the code I am using as well :)
Sample Input:
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<OrderCreate Version="5.1.1" xmlns="urn:midx:names:specification:ces:schema:all:5:1:1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<ThisDocumentIdentifier>
<DocumentIdentifier>58585993</DocumentIdentifier>
</ThisDocumentIdentifier>
<ThisDocumentDateTime>
<DateTime DateTimeQualifier="On">2014-08-22T00:00:00Z</DateTime>
</ThisDocumentDateTime>
<From>
<PartnerInformation>
<PartnerName>MOSLLC</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0089646370000</PartnerIdentifier>
<ContactInformation>
<ContactName>MOSLLC </ContactName>
<ContactName>804-281-1402</ContactName>
<EmailAddress></EmailAddress>
</ContactInformation>
</PartnerInformation>
</From>
<To>
<PartnerInformation>
<PartnerName>Walmart</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0062668030000</PartnerIdentifier>
</PartnerInformation>
</To>
</Header>
<OrderCreateBody>
<OrderCreateProperties>
<PurchaseOrderNumber>
<DocumentIdentifier>OD3157538</DocumentIdentifier>
</PurchaseOrderNumber>
<PurchaseOrderTypeCode Domain="ANSI-ASC-X12-92">KN</PurchaseOrderTypeCode>
<PurchaseOrderIssuedDate>
<DateTime DateTimeQualifier="On">2014-08-22T00:00:00Z</DateTime>
</PurchaseOrderIssuedDate>
<LanguageCode Domain="ISO-639-2T">eng</LanguageCode>
<CurrencyCode Domain="ISO-4217">USD</CurrencyCode>
<BuyerSequenceNumber>0</BuyerSequenceNumber>
<DeliveryTerms>
<DeliveryTermsCode Domain="Incoterms-2000">CPT</DeliveryTermsCode>
<DeliveryTermsLocation>ORIGIN</DeliveryTermsLocation>
</DeliveryTerms>
<ShipmentMethodOfPaymentCode Domain="ANSI-ASC-X12-146">PC</ShipmentMethodOfPaymentCode>
<PaymentTerms>
<PaymentTermsOfSale>
<TermsOfSaleDescription>DUE 25TH OF FOLLOWING MONTH</TermsOfSaleDescription>
<NetDaysDue>0</NetDaysDue>
</PaymentTermsOfSale>
</PaymentTerms>
</OrderCreateProperties>
<OrderCreatePartners>
<Buyer>
<PartnerInformation>
<PartnerName>MOSLLC</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0089646370000</PartnerIdentifier>
<ContactInformation>
<ContactName>MOSLLC LLC</ContactName>
<ContactNumber>804-281-1402</ContactNumber>
<EmailAddress>Jim.Paul#sscoop.com</EmailAddress>
</ContactInformation>
</PartnerInformation>
</Buyer>
<Seller>
<PartnerInformation>
<PartnerName>WalmartPartnerName</PartnerName
<PartnerIdentifier Agency="IBM-EBID">0062668030000</PartnerIdentifier>
</PartnerInformation>
</Seller>
<ShipTo>
<PartnerInformation>
<PartnerName>ORANGE MADISON COOP ORANGE BR</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0238626420000</PartnerIdentifier>
<AddressInformation>
<AddressLine>13323 JAMES MADISON HWY</AddressLine>
<CityName>ORANGE</CityName>
<StateOrProvince>VA</StateOrProvince>
<PostalCode>22960</PostalCode>
<PostalCountry>US</PostalCountry>
</AddressInformation>
</PartnerInformation>
</ShipTo>
<Payer>
<PartnerInformation>
<PartnerName>MOSLLC</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0089646370000</PartnerIdentifier>
</PartnerInformation>
</Payer>
</OrderCreatePartners>
<OrderCreateDetails>
<OrderCreateProductLineItem>
<LineNumber>1</LineNumber>
<PurchaseOrderLineItemNumber>1</PurchaseOrderLineItemNumber>
<ProductIdentification>
<ProductIdentifier Agency="AssignedByManufacturer">883580921503</ProductIdentifier>
<ProductName>HARNESS XTRA 5.6L RUP BULK</ProductName>
<ProductDescription>HARNESS XTRA 5.6L RUP BULK</ProductDescription>
</ProductIdentification>
<ProductQuantity>
<Measurement>
<MeasurementValue>1000</MeasurementValue>
<UnitOfMeasureCode Domain="UN-Rec-20">GLL</UnitOfMeasureCode>
</Measurement>
</ProductQuantity>
<ScheduleDateTimeInformation ScheduleType="RequestedDelivery">
<DateTimeInformation>
<DateTime DateTimeQualifier="On">2014-08-22T00:00:00Z</DateTime>
</DateTimeInformation>
</ScheduleDateTimeInformation>
</OrderCreateProductLineItem>
</OrderCreateDetails>
</OrderCreateBody>
</OrderCreate>
</soapenv:Body>
Expected output:
<?xml version="1.0" encoding="UTF-8"?><soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<OrderCreate Version="2.0.2">
<Header xmlns="urn:midx:names:specification:ces:schema:all:5:1:1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ThisDocumentIdentifier>
<DocumentIdentifier>58585993</DocumentIdentifier>
</ThisDocumentIdentifier>
<ThisDocumentDateTime>
<DateTime xmlns="" DateTimeQualifier="On">20140822000000</DateTime>
</ThisDocumentDateTime>
<From>
<PartnerInformation>
<PartnerName>MOSLLC</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0089646370000</PartnerIdentifier>
<ContactInformation>
<ContactName>MOSLLC </ContactName>
<ContactName>804-281-1402</ContactName>
<EmailAddress/>
</ContactInformation>
</PartnerInformation>
</From>
<To>
<PartnerInformation>
<PartnerName>Walmart</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0062668030000</PartnerIdentifier>
</PartnerInformation>
</To>
</Header>
<OrderCreateBody xmlns="urn:midx:names:specification:ces:schema:all:5:1:1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OrderCreateProperties>
<PurchaseOrderNumber>
<DocumentIdentifier>OD3157538</DocumentIdentifier>
</PurchaseOrderNumber>
<PurchaseOrderTypeCode Domain="ANSI ASC X12 92">KN</PurchaseOrderTypeCode>
<PurchaseOrderIssuedDate>
<DateTime xmlns="" DateTimeQualifier="On">20140822000000</DateTime>
</PurchaseOrderIssuedDate>
<LanguageCode Domain="ISO 639-2/T">eng</LanguageCode>
<CurrencyCode Domain="ISO 4217">USD</CurrencyCode>
<BuyerSequenceNumber>0</BuyerSequenceNumber>
<DeliveryTerms>
<DeliveryTermsCode Domain="Incoterms-2000">CPT</DeliveryTermsCode>
<DeliveryTermsLocation>ORIGIN</DeliveryTermsLocation>
</DeliveryTerms>
<ShipmentMethodOfPaymentCode Domain="ANSI-ASC-X12-146">PC</ShipmentMethodOfPaymentCode>
<PaymentTerms>
<PaymentTermsOfSale>
<TermsOfSaleDescription>DUE 25TH OF FOLLOWING MONTH</TermsOfSaleDescription>
<NetDaysDue>0</NetDaysDue>
</PaymentTermsOfSale>
</PaymentTerms>
</OrderCreateProperties>
<OrderCreatePartners>
<Buyer>
<PartnerInformation>
<PartnerName>MOSLLC</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0089646370000</PartnerIdentifier>
<ContactInformation>
<ContactName>MOSLLC LLC</ContactName>
<TelephoneNumber>
<NationalPhoneNumber>813-217-9512</NationalPhoneNumber>
</TelephoneNumber>
<ContactNumber>804-281-1402</ContactNumber>
<EmailAddress>Jim.Paul#sscoop.com</EmailAddress>
</ContactInformation>
</PartnerInformation>
</Buyer>
<Seller>
<PartnerInformation>
<PartnerName>WalmartPartnerName</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0062668030000</PartnerIdentifier>
</PartnerInformation>
</Seller>
<ShipTo>
<PartnerInformation>
<PartnerName>ORANGE MADISON COOP ORANGE BR</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0238626420000</PartnerIdentifier>
<AddressInformation>
<AddressLine>13323 JAMES MADISON HWY</AddressLine>
<CityName>ORANGE</CityName>
<StateOrProvince>VA</StateOrProvince>
<PostalCode>22960</PostalCode>
<PostalCountry>US</PostalCountry>
</AddressInformation>
</PartnerInformation>
</ShipTo>
<Payer>
<PartnerInformation>
<PartnerName>MOSLLC</PartnerName>
<PartnerIdentifier Agency="IBM-EBID">0089646370000</PartnerIdentifier>
</PartnerInformation>
</Payer>
</OrderCreatePartners>
<OrderCreateDetails>
<OrderCreateProductLineItem>
<LineNumber>1</LineNumber>
<PurchaseOrderLineItemNumber>1</PurchaseOrderLineItemNumber>
<ProductIdentification>
<ProductIdentifier Agency="AssignedByManufacturer">883580921503</ProductIdentifier>
<ProductName>HARNESS XTRA 5.6L RUP BULK</ProductName>
<ProductDescription>HARNESS XTRA 5.6L RUP BULK</ProductDescription>
</ProductIdentification>
<ProductQuantity>
<Measurement>
<MeasurementValue>1000</MeasurementValue>
<UnitOfMeasureCode Domain="UN-Rec-20">GLL</UnitOfMeasureCode>
</Measurement>
</ProductQuantity>
<ScheduleDateTimeInformation ScheduleType="RequestedDelivery">
<DateTimeInformation>
<DateTime xmlns="" DateTimeQualifier="On">20140822000000</DateTime>
</DateTimeInformation>
</ScheduleDateTimeInformation>
</OrderCreateProductLineItem>
</OrderCreateDetails>
</OrderCreateBody>
</OrderCreate>
</soapenv:Body>
This is the part which needs to be added
After element Buyer/ContactDescription I need add this
<TelephoneNumber>
<NationalPhoneNumber>605225-1372</NationalPhoneNumber>
</TelephoneNumber>
This is the sample code I wrote. Can anyone please guide me?
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" extension-element-prefixes="dp">
<xsl:output method="xml"/>
<xsl:template match="attribute::Domain[starts-with(name(..),'PurchaseOrderType')]">
<xsl:attribute name="Domain"><xsl:value-of select="translate(., '-', ' ')"/></xsl:attribute>
</xsl:template>
<xsl:template match="attribute::*">
<xsl:copy/>
</xsl:template>
<xsl:template match="attribute::Domain[starts-with(name(..),'CurrencyCode')]">
<xsl:attribute name="Domain"><xsl:value-of select="translate(., '-', ' ')"/></xsl:attribute>
</xsl:template>
<xsl:template match="attribute::*">
<xsl:copy/>
</xsl:template>
<!-- <xsl:template match="attribute::Domain[starts-with(name(..),'LanguageCode')]">
<xsl:attribute name="Domain"><xsl:value-of select="translate('.', '-', ' ')"/>
</xsl:attribute>
</xsl:template>
-->
<xsl:template match="attribute::Domain[starts-with(name(..),'LanguageCode')]">
<xsl:attribute name="Domain"><xsl:value-of select="concat('ISO ',substring-after(substring-before(.,'T'),'-'), '/T')"/></xsl:attribute>
</xsl:template>
<xsl:template match="attribute::*">
<xsl:copy/>
</xsl:template>
<xsl:template match="*[local-name()='DateTime']">
<DateTime>
<xsl:copy-of select="attribute::*"/>
<xsl:value-of select="translate(., '-T:Z', '')"/>
</DateTime>
</xsl:template>
<xsl:template match="*[local-name()='OrderCreate']">
<OrderCreate Version="2.0.2">
<xsl:apply-templates select="node()"/>
</OrderCreate>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="attribute::*|node()"/>
</xsl:element>
<!--Adding the elements
<TelephoneNumber>
<NationalPhoneNumber>605225-1372</NationalPhoneNumber>
</TelephoneNumber>-->
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="attribute::*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Buyer/ContactName">
<xsl:copy-of select="."/>
<xsl:element name="TelephoneNumber">
<xsl:attribute name="NationalPhoneNumber">605225-1372</xsl:attribute>
</xsl:element>
<!--<TelephoneNumber>
<NationalPhoneNumber>605225-1372</NationalPhoneNumber>
</TelephoneNumber>-->
</xsl:template>
</xsl:stylesheet>
To fix your issue you need two changes:
Specify the default namespace of your document in the root tag using some prefix, e.g. "my":
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="urn:midx:names:specification:ces:schema:all:5:1:1"
xmlns:dp="http://www.datapower.com/extensions" extension-element-prefixes="dp">
Fix your Buyer template:
<xsl:template match="my:Buyer/my:PartnerInformation/my:ContactInformation/my:ContactName">
<xsl:copy-of select="."/>
<TelephoneNumber xmlns="urn:midx:names:specification:ces:schema:all:5:1:1">
<NationalPhoneNumber>605225-1372</NationalPhoneNumber>
</TelephoneNumber>
</xsl:template>
Thank you Lagivan and Mathias. Can you please explain the use of adding the namespace?
The answer is too long to be added in a comment, that is why I write a separate answer, even though #lagivan has already given an answer in terms of code.
The reason why adding the namespace solves your problem is that elements with a namespace are different from ones without a namespace, even if their element names are the same. Or put in another way,
<ns:number xmlns:ns="www.ns.com"/>
is entirely different from
<number>
ns:number is said to be prefixed, which is shorthand for saying it belongs to a certain namespace, in this case www.ns.com. Besides, there is a way to define a default namespace:
<number xmlns="www.ns.com">
<digit/>
</number>
In the example above, there is a default namespace defined on the number element. This does not have any effect for the number element itself, but all descendants of number (in this case only digit) will take on this namespace.
Now, turning to your specific problem, the element you'd like to match (ContactName) is not itself prefixed, but it has a default namespace. This default namespace is not declared on the ContactName element, but higher up in the tree, on the OrderCreate element:
<OrderCreate Version="5.1.1" xmlns="urn:midx:names:specification:ces:schema:all:5:1:1">
Any descendant of OrderCreate will be in the namespace urn:midx:names:specification:ces:schema:all:5:1:1, for example ... ContactName.
What this means for your XSLT code is that if you want to match the ContactName element from the input, you must declare this namespace in your XSLT stylesheet and prefix the element name to be able to find it.
<xsl:stylesheet xmlns:my="urn:midx:names:specification:ces:schema:all:5:1:1">
Now you can write templates to match the descendant elements of OrderCreate, always prefixing them with my::
<xsl:template match="my:ContactName">
On the other hand,
<xsl:template match="ContactName">
will never match anything because such an element (one that is called "ContactName" and one that is not in any namespace) does not exist in your input XML.
I have to pick text from translation.xml and update skeleton.xml's respective (where #xid =#id) nodes . in other words IF #id of translation.xml matches with #xid of skeleton.xml, the text content should be placed under skeleton.xml (+ if there is child element present the text content (inline element i, b, etc) also should go in respective parent element: Please see example below for more details:
Note: the inline element could be anything in skeleton.xml (its not restrict to b or i, so it should be generic)
skeleton.xml
<root>
<para a="b" b="c">
<text xid="1">This is first para <b xid="2" a="c" b="d">This is bold <i xid="3" b="d" c="e">This is italics</i> rest of bold</b> rest of para</text>
</para>
<para><text xid="4">This is second para</text></para>
<para><text xid="5">This is unchanged para</text></para>
<para><text xid="6">This is unchanged para</text></para>
</root>
translation.xml
<root>
<TU id="1">
<source>This is first para <g id="2" tagName="b">This is bold <g id="3" tagName="i">This is italics</g> rest of bold</g> rest of para</source>
<target>suum primum para <g id="2" tagName="b">Et hoc confidens, <g id="3" tagName="i">Hoc est, Te Deum</g> Reliqua autem audet,</g> reliqua autem verba haec</target>
</TU>
<TU id="4">
<source>This is second para</source>
<target>Hoc est secundum verba haec</target>
</TU>
</root>
UpdatedSkeleton.xml
<root>
<para a="b" b="c">
<text xid="1">suum primum para <b xid="2" a="c" b="d">Et hoc confidens, <i xid="3" b="d" c="e">Hoc est, Te Deum</i> Reliqua autem audet,</b> reliqua autem verba haec</text>
</para>
<para><text xid="4">Hoc est secundum verba haec</text></para>
<para><text xid="5">This is unchanged para</text></para>
<para><text xid="6">This is unchanged para</text></para>
</root>
I am trying with this code, but facing challenge to place text of inline content at the right place:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:param name="translation" select="'file:/C:/Skeleton.xml'"></xsl:param>
<xsl:variable name="doc">
<xsl:copy-of select="doc($translation)"/>
</xsl:variable>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text">
<xsl:variable name="skelID" select="#xid"/>
<xsl:choose>
<xsl:when test="$doc//*[$skelID=#id]">
<xsl:apply-templates select="$doc//*[$skelID=#id]/target"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
You can copy the <text> node adding <xsl:copy> to your test block, and copy the xid attribute using <xsl:attribute>. For the unmodified nodes, you can use <xsl:copy-of> which copies the full tree, including attributes:
<xsl:when test="$doc//*[$skelID=#id]">
<xsl:copy>
<xsl:attribute name="xid">
<xsl:value-of select="$skelID"/>
</xsl:attribute>
<xsl:apply-templates select="$doc//*[$skelID=#id]/target"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
That will also copy the <target> element. You can remove it adding a template:
<xsl:template match="target">
<xsl:apply-templates/>
</xsl:template>
You also aren't replacing the <g> tag. I assume the #tagName attribute says what it's supposed to be transformed into. This should do it:
<xsl:template match="g">
<xsl:element name="{#tagName}">
<xsl:attribute name="xid">
<xsl:value-of select="#id"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
I might have missed something, but that will probably solve most of your problem.
I want to write a template to process some section and reuse it.
In the below XML, we see Message is repeated in every ,,. I want to write a template to process and call it when ever needed.
<Data>
<A>
<text>this is text</text>
<Message>
<local>Local link</local>
<STD>External link</STD>
</Message>
</A>
<B>
<info>Information</info>
<Message>
<local>Local uri link</local>
<STD>External link uri</STD>
</Message>
</B>
<C>
<longtext>Long Text</longtext>
<Message>
<local>Local uri link</local>
<STD>External link uri</STD>
</Message>
</C>
<Data>
Output needed:
<Information>
<AA>
this is text
<MSG local value="Local uri link" STD value="External link"/>
</AA>
<BB>
Information
<MSG local value ="Local uri link" STD value="External link"/>
</BB>
<CC>
Long Text
<MSG local value="Local uri link" STD value="External link"/>
</CC>
<Information>
While processing tag in every node, I am writing code for every tags in A, B, C.
Sample code written
<Information>
<xsl:template match="A">
<AA>
<xsl:value-of select="text"/>
<xsl:element name="MSG">
<xsl:attribute name="local value">
<xsl:value-of select="Message/local"/>
</xsl:attribute>
<xsl:attribute name="STD value">
<xsl:value-of select="Message/STD"/>
</xsl:attribute>
</AA>
</Information>
similarly for every template I am explicitly writing the code for the block MSG.
Now I want to write a separate template to process . And I want to call this template from every template.
Basically I want to reuse the code written to process
Can any one help me how to do it.
Thank you.
Here is a sample:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Data">
<Information>
<xsl:apply-templates/>
</Information>
</xsl:template>
<xsl:template match="Data/*">
<xsl:element name="{local-name()}{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="Data/A/text | Data/B/info | Data/C/longtext">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Message">
<MSG local-value="{local}" STD-value="{STD}"/>
</xsl:template>
</xsl:stylesheet>
When applied to the input
<Data>
<A>
<text>this is text</text>
<Message>
<local>Local link</local>
<STD>External link</STD>
</Message>
</A>
<B>
<info>Information</info>
<Message>
<local>Local uri link</local>
<STD>External link uri</STD>
</Message>
</B>
<C>
<longtext>Long Text</longtext>
<Message>
<local>Local uri link</local>
<STD>External link uri</STD>
</Message>
</C>
</Data>
Saxon 6.5.5 outputs
<?xml version="1.0" encoding="utf-8"?><Information>
<AA>
this is text
<MSG local-value="Local link" STD-value="External link"/>
</AA>
<BB>
Information
<MSG local-value="Local uri link" STD-value="External link uri"/>
</BB>
<CC>
Long Text
<MSG local-value="Local uri link" STD-value="External link uri"/>
</CC>
</Information>
Neither your posted input sample nor the wanted output sample are well-formed XML so I had to make some changes to element or attribute names to process as well as to output XML.
I would like to select all descendant but "blog" nodes. For the example, only subtree should appear on output.
I'm trying this xsl code:
<xsl:template match="rdf:RDF">
<xsl:copy>
<xsl:copy-of select="descendant::*[not(descendant::blog)]"/>
</xsl:copy>
</xsl:template>
for this xml:
<rdf:RDF>
<profesor rdf:ID="profesor_39">
<nombre rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>Augusto</nombre>
</profesor>
<blog rdf:ID="blog_41">
<entradas>
<entrada_blog rdf:ID="entrada_blog_42">
<etiquetas>
<tecnologia rdf:ID="tecnologia_49">
<termino rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>Atom</termino>
</tecnologia>
</etiquetas>
<autor>
<alumno rdf:ID="alumno_38">
<nombre rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>Jesus</nombre>
</alumno>
</autor>
</entrada_blog>
</entradas>
<autores rdf:resource="#alumno_38"/>
<direccion rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>http://tfg1.unex.es/10comunidad/wordpress/</direccion>
</blog>
</rdf:RDF>
What am I missing? "blog" nodes are still printed on the output.
Thank you.
Here's a complete solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- By default, recursively copy all nodes unchanged -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!-- But strip out <blog> -->
<xsl:template match="blog"/>
<!-- If you want to strip out just the <blog> start and end tags, use this instead:
<xsl:template match="blog">
<xsl:apply-templates/>
</xsl:template>
-->
</xsl:stylesheet>
To omit blog and all its children:
<xsl:template match="RDF">
<xsl:copy-of select="child::node()[name() != 'blog']"/>
</xsl:template>
To omit blog but still o/p its children:
<xsl:template match="RDF">
<xsl:copy-of select="descendant::node()[name() != 'blog']"/>
</xsl:template>
The condition not(descendant::blog) excludes any node that have a descendant named "blog".
So if you have:
<blog id="1">
<test id="1.1">
<blog id="1.1.1" />
</test>
</blog>
<blog id="2">
<test id="2.1" />
</blog>
It will exclude <blog id="1"> and <test id="1.1">, because these nodes both have <blog id="1.1.1"> as a descendant.
But it won't exclude <blog id="1.1.1"> or <blog id="2"> because they don't have any descendant named "blog"
Also note that your select of descendant::*[not(descendant::blog)] will output <test id="2.1"> twice: once within <blog id="2">, and once again by itself.
For a complete solution, the one suggested by Evan Lenz (identity transform with a blank overriding template for "blog" nodes) is probably the one that gives the result you wanted.