Copy XML replacing selected node contents in XSLT (2.0)
Here should go questions about transforming XML with XSLT and FOP.
-
- Posts: 8
- Joined: Tue Dec 11, 2007 1:52 pm
Copy XML replacing selected node contents in XSLT (2.0)
I'm wondering if there is a way in XSLT (2.0 is fine) to copy some part of XML replacing some node values at the same time. Here is an example to visualize the matter:
<invoice>
[...]
<apples>
<apple id=1"><price>100</price></apple>
<apple id=2"><price>120</price></apple>
<apple id=3"><price>90</price></apple>
</apples>
<update-prices>
<modification><price apple-id="1">112</price></modification>
<modification><price apple-id="2">132</price></modification>
<modification><price apple-id="3">102</price></modification>
</update-prices>
[...]
</invoice>
So, I would like to prepare an XSLT stylesheet which copies the whole <invoice> element with its children, but replacing the apple prices [isn't $100 for an apple high enough? damn inflation...] with new prices that are included in the <update-prices> element.
It would be nice to delete the <update-prices> element in the resulting document as well.
So the result XML should look like this:
<invoice>
[...]
<apples>
<apple id=1"><price>112</price></apple>
<apple id=2"><price>132</price></apple>
<apple id=3"><price>102</price></apple>
</apples>
[...]
</invoice>
I would not like to map every possible node that can appear in the XML file accordning to the schema. I would just like to copy and paste the XML replacing some of the values using a pattern. Is there a non-hacker way to do this in XSLT?
<invoice>
[...]
<apples>
<apple id=1"><price>100</price></apple>
<apple id=2"><price>120</price></apple>
<apple id=3"><price>90</price></apple>
</apples>
<update-prices>
<modification><price apple-id="1">112</price></modification>
<modification><price apple-id="2">132</price></modification>
<modification><price apple-id="3">102</price></modification>
</update-prices>
[...]
</invoice>
So, I would like to prepare an XSLT stylesheet which copies the whole <invoice> element with its children, but replacing the apple prices [isn't $100 for an apple high enough? damn inflation...] with new prices that are included in the <update-prices> element.
It would be nice to delete the <update-prices> element in the resulting document as well.
So the result XML should look like this:
<invoice>
[...]
<apples>
<apple id=1"><price>112</price></apple>
<apple id=2"><price>132</price></apple>
<apple id=3"><price>102</price></apple>
</apples>
[...]
</invoice>
I would not like to map every possible node that can appear in the XML file accordning to the schema. I would just like to copy and paste the XML replacing some of the values using a pattern. Is there a non-hacker way to do this in XSLT?
-
- Posts: 89
- Joined: Mon Mar 06, 2006 10:13 pm
Start off with a copy template
---
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
---
Then have an apple template.
Notice the check for a price modification. Unfortunately this method is a little bit slower, since we have to check every apple for a modification, but I don't entirely see a workaround.
---
<xsl:template match="apple">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:choose>
<xsl:when test="//update-prices/modification/price/@apple-id[.=current()/@id]">
<xsl:apply-templates select="//update-prices/modification/price[@apple-id=current()/@id]"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
---
Don't process the update-prices node directly
---
<xsl:template match="update-prices"/>
---
And add a modification to the price node template so we don't copy the apple-id attribute
---
<xsl:template match="price">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
---
As a side, you can also add a key to the price-modifications if you have a lot of them, and it is worth indexing.
---
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
---
Then have an apple template.
Notice the check for a price modification. Unfortunately this method is a little bit slower, since we have to check every apple for a modification, but I don't entirely see a workaround.
---
<xsl:template match="apple">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:choose>
<xsl:when test="//update-prices/modification/price/@apple-id[.=current()/@id]">
<xsl:apply-templates select="//update-prices/modification/price[@apple-id=current()/@id]"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
---
Don't process the update-prices node directly
---
<xsl:template match="update-prices"/>
---
And add a modification to the price node template so we don't copy the apple-id attribute
---
<xsl:template match="price">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
---
As a side, you can also add a key to the price-modifications if you have a lot of them, and it is worth indexing.
Jump to
- Oxygen XML Editor/Author/Developer
- ↳ Feature Request
- ↳ Common Problems
- ↳ DITA (Editing and Publishing DITA Content)
- ↳ SDK-API, Frameworks - Document Types
- ↳ DocBook
- ↳ TEI
- ↳ XHTML
- ↳ Other Issues
- Oxygen XML Web Author
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Content Fusion
- ↳ Feature Request
- ↳ Common Problems
- Oxygen JSON Editor
- ↳ Feature Request
- ↳ Common Problems
- Oxygen PDF Chemistry
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Feedback
- ↳ Feature Request
- ↳ Common Problems
- Oxygen XML WebHelp
- ↳ Feature Request
- ↳ Common Problems
- XML
- ↳ General XML Questions
- ↳ XSLT and FOP
- ↳ XML Schemas
- ↳ XQuery
- NVDL
- ↳ General NVDL Issues
- ↳ oNVDL Related Issues
- XML Services Market
- ↳ Offer a Service