Reputation: 69
I am trying to parse file manager.xml to get a proper structure of data I need. Example of manager.xml:
<?xml version="1.0" encoding="koi8-r"?>
<manager>
<priv id="pr.screen.access" caption="c.screen.access">
<priv id="pr.screen.category.documents" caption="c.main.documents">
<priv id="pr.screen.category.documents.rcn" caption="c.main.documents.rcn">
<priv id="pr.screen.category.documents.rcn.create" caption="c.main.documents.rcn.create"/>
</priv>
</priv>
</priv>
<priv id="pr.screen.category.archives" caption="c.main.archives"/>
<priv id="pr.screen.category.documents.rcn.create_as" caption="c.main.documents.rcn.create_as" parent="pr.screen.access"/>
<priv id="pr.screen.category.transport_management.documents" caption="c.main.transport_management.documents"/>
<caption id="c.screen.access">
<loctext lang="ru" long="access"/>
</caption>
<caption id="c.main.documents">
<loctext lang="ru" long="documents"/>
</caption>
<caption id="c.main.documents.rcn">
<loctext lang="ru" long="rcn"/>
</caption>
<caption id="c.main.documents.rcn.create">
<loctext lang="ru" long="rcn_create"/>
</caption>
<caption id="c.main.archives">
<loctext lang="ru" long="archives"/>
</caption>
<caption id="c.main.documents.rcn.create_as">
<loctext lang="ru" long="rcn_create-as"/>
</caption>
<caption id="c.main.transport_management.documents">
<loctext lang="ru" long="transport_documents"/>
</caption>
</manager>
Basically I need to copy all "priv" elements with all nested elements and also find "priv" elements with "parent" attribute and put it into respective "priv" element with "id" attribute equal to "parent".
Besides that I also need to add "caption_ru" attribute for every "priv" element with the value fetched from attribute "long" of "loctext" element which is inside "caption" element where "id" attribute is equal to "caption" attribute of "priv". This part is working, but is there any chance that it's better to be solved by using xsl:key function?
I have next xslt, which is working almost as intended, but I am stuck with extra "priv" elements which I get after tranformation and I can't find any way to get rid of them: xsl:
<?xml version="1.0" encoding="koi8-r"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="koi8-r" version="1.0"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:attribute name='caption_ru'>
<xsl:value-of select="//manager/caption[@id=current()/@caption]/loctext[@lang='ru']/@long"/>
</xsl:attribute>
<xsl:apply-templates select="@* | priv[not(@parent)]"/>
<xsl:call-template name="nested_priv"/>
<!--xsl:copy>
<xsl:apply-templates select="//manager/priv[@parent=current()/@id]"/>
</xsl:copy-->
</xsl:copy>
</xsl:template>
<xsl:template name="nested_priv">
<xsl:copy>
<!--xsl:attribute name='caption_ru'>
<xsl:value-of select="//manager/caption[@id=current()/@caption]/loctext[@lang='ru']/@long"/>
</xsl:attribute-->
<xsl:apply-templates select="//manager/priv[@parent=current()/@id]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This is what I get after transformation:
<?xml version="1.0" encoding="koi8-r"?>
<manager caption_ru="">
<priv caption_ru="access" id="pr.screen.access" caption="c.screen.access">
<priv caption_ru="documents" id="pr.screen.category.documents" caption="c.main.documents">
<priv caption_ru="rcn" id="pr.screen.category.documents.rcn" caption="c.main.documents.rcn">
<priv caption_ru="rcn_create" id="pr.screen.category.documents.rcn.create" caption="c.main.documents.rcn.create">
<priv/>
</priv>
<priv/>
</priv>
<priv/>
</priv>
<priv>
<priv caption_ru="rcn_create-as" id="pr.screen.category.documents.rcn.create_as" caption="c.main.documents.rcn.create_as" parent="pr.screen.access">
<priv/>
</priv>
</priv>
</priv>
<priv caption_ru="archives" id="pr.screen.category.archives" caption="c.main.archives">
<priv/>
</priv>
<priv caption_ru="transport_documents" id="pr.screen.category.transport_management.documents" caption="c.main.transport_management.documents">
<priv/>
</priv>
<manager/>
</manager>
Upvotes: 1
Views: 147
Reputation: 69
Resolved with xsl listed above which is based on the answer of user3016153 whom I am very thankful. I am not sure should I accept his answer or not, but I did since it was very helpful.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="koi8-r" indent="yes"/>
<xsl:key name="caption" match="caption" use="@id" />
<xsl:key name="child_priv" match="priv" use="@parent"/>
<xsl:template match="/manager">
<xsl:copy>
<xsl:apply-templates select="priv[not(@parent)]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="priv">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="caption_ru">
<xsl:value-of select="key('caption', @caption)/loctext[@lang='ru']/@long" />
</xsl:attribute>
<xsl:apply-templates select="priv"/>
<xsl:apply-templates select="key('child_priv',current()/@id)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Reputation: 117100
How about this way?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="koi8-r" indent="yes"/>
<xsl:key name="caption" match="caption" use="@id" />
<xsl:template match="/manager">
<xsl:copy>
<xsl:apply-templates select="priv"/>
</xsl:copy>
</xsl:template>
<xsl:template match="priv">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="caption_ru">
<xsl:value-of select="key('caption', @caption)/loctext/@long" />
</xsl:attribute>
<xsl:apply-templates select="priv"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0