0

I am struggling with the following issue: In the below XML, I need to remove the attribute restrict="restrict" if the attribute is nested within an element that also contains an attribute restrict="restrict". I also need to remove the element restrict if it is nested within an element containing an attribute restrict="restrict". However, if a restrict="restrict" appears on a nested element whose ancestor does not contain an attribute restrict="restrict", I need to keep it. The same goes for the restrict element. I need to keep it if it is not nested in a restrict element or within an element that does not have the restrict="restrict" attribute.

<book hasrestrict="yes"> 
<story> <part partno="1"> <parttitle>Title of the Part</parttitle> 
<chapter chapno="11"> <chaptertitle>Title of the Chapter</chaptertitle> 
<section id="id3321234" secno="23">
<sectiontitle>Title of the Section</sectiontitle> 
<toc/> 
<subsection1 restrict="restrict">
<date>(09-23-2012)</date> 
<title>Subsection Title</title> 
<p>Text that makes up the paragraph of the subsetion1. <restrict>This information is  
restricted.</restrict></p> 
<p restrict="restrict">Here is some text in another paragraph that is
restricted. The restrict attribute of the paragraph needs to be
removed because a restrict attribute is already specified for
subsection1. Everything that appears within the element of subsection
1 is already restricted, so I need to remove the unnecessary restrict
attribute from the paragraph because it is causing havoc when my
publishing system tries to format the document.</p>
<subsection2><title>Title of Subsection2</title> 
<p>This is text that appears in a subsecion2 paragraph. 
<list><li>This is an item in a list <restrict>that has restricted content</restrict></li>
<li>Second item</li> 
<li>Third item</li></list></p> 
<subsection3 restrict="restrict">
<title>Title of Subsection3</title> 
<p>Text appearing in a paragraph in subsction 3 
<table frame="all"> <tgroup cols="3" colsep="1" rowsep="1"> 
<colspec colname="col1"/> <colspec colname="col2"/> 
<colspec colname="col3"/>
<thead><row><entry>Entry1</entry>
<entry>Entry2</entry>
<entry>Entry3 <restrict>with restricted information</restrict></entry></row></thead>
<tbody><row><entry restrict="restrict">text</entry>
<entry>text</entry>
<entry>text</entry></row>
</tbody></tgroup></table></p></subsection3></subsection2></subsection1>
<subsection1><date>(09-23-2012)</date> 
<title>Subsection Title</title>
<p>Text that makes up the paragraph of the subsetion1. <restrict>This information is
restricted.</restrict></p> 
<p restrict="restrict">Here is some text in another paragraph that is
restricted. </p> 
<subsection2 restrict="restrict"><title>Title of Subsection2</title>
<p>This is text that appears in a subsecion2 paragraph.</p>
</subsection2></subsection1></section></chapter></part></story></book>

I am new to xsl, and have attempted to write the translation, but I am not having much luck.

The desired out put should look like this:

<book hasrestrict="yes">
<story>
<part partno="1">
<parttitle>Title of the Part</parttitle>
<chapter chapno="11">
<chaptertitle>Title of the Chapter</chaptertitle>
<section id="id3321234" secno="23">
<sectiontitle>Title of the Section</sectiontitle>
<toc/>
<subsection1 restrict="restrict"><date>(09-23-2012)</date>
<title>Subsection Title</title>
<p>Text that makes up the paragraph of the subsetion1. This information is restricted.</p>
<p>Here is some text in another paragraph that is restricted. The restrict attribute of the paragraph needs to be removed because a restrict attribute is already specified for subsection1. Everything that appears within the element of subsection1 is already restricted, so I need to remove the unnecessary restrict attribute from the paragraph because it is causing havoc when my publishing system tries to format the document.</p>
<subsection2><title>Title of Subsection2</title>
<p>This is text that appears in a subsecion2 paragraph.
<list>
<li>This is an item in a list that has restricted content</li>
<li>Second item</li>
<li>Third item</li></list></p>
<subsection3><title>Title of Subsection3</title>
<p>Text appearing in a paragraph in subsction 3
<table frame="all">
<tgroup cols="3" colsep="1" rowsep="1">
<colspec colname="col1"/>
<colspec colname="col2"/>
<colspec colname="col3"/>
<thead><row><entry>Entry1</entry>
<entry>Entry2</entry>
<entry>Entry3 with restricted information</entry></row></thead>
<tbody><row>text</entry>
<entry>text</entry>
<entry>text</entry></row></tbody></tgroup></table></p></subsection3></subsection2></subsection1>
<subsection1><date>(09-23-2012)</date>
<title>Subsection Title</title><p>Text that makes up the paragraph of the subsetion1. <restrict>This information is restricted.</restrict></p>
<p restrict="restrict">Here is some text in another paragraph that is restricted. </p>
<subsection2 restrict="restrict"><title>Title of Subsection2</title><p>This is text that appears in a subsecion2 paragraph.</p></subsection2></subsection1></section></chapter></part></story></book>

Here is the code I have attempted:

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="@restrict">
  <xsl:if test="ancestor::*[@restrict='restrict']">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:if>
</xsl:template>

<xsl:template match="restrict">
  <xsl:if test="ancestor::*[@restrict='restrict']">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:if>
</xsl:template>

<xsl:template match="restrict"> 
  <xsl:if test="ancestor::restrict">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:if>
</xsl:template>     
</xsl:transform>

This is not working for me. I receive an error stating

"WARNING org.xml.sax.SAXParseException: The child axis starting at an attribute node will never select anything"

I really don't know how to go about doing this. Any suggestions (and explanation) would be greatly appreciated.

123CSRPIN
  • 7
  • 5
  • That's actually a warning, not an error -- the transform still succeeds. The warning is letting you know that your `` is not going to do anything. Can you explain more what part of the current XSLT output is problematic? – JKesMc9tqIQe9M Dec 04 '14 at 14:05
  • I am not achieving the desired output. If the ancestor (let's use subsection1) has an attribute of restrict, then I need to remove all of the restrict attributes on every descendent as well as every restrict element contained within subsection 1. However, if the ancestor does not contain a restrict attribute, I need to keep the restrict elements and attributes of the descendants, but I cannot have a restrict element nested within a restrict element. When I run the above code, nothing happens. – 123CSRPIN Dec 04 '14 at 14:23

2 Answers2

1

As you are using the identity template, you don't really need to code extra logic for the elements or attributes you wish to keep; whether they are restrict ones or not. You only really need to add templates for the things you wish to remove.

You say "need to remove the attribute restrict="restrict" if the attribute is nested within an element that also contains an attribute restrict="restrict". Well, the template to do this would be like so:

<xsl:template match="../ancestor::*[@restrict='restrict']]" />

(The .. here is to ignore the current element which has the current restrict element)

And to "to remove the element restrict if it is nested within an element containing an attribute restrict="restrict".", the template would look like this

<xsl:template match="restrict[ancestor::*[@restrict='restrict']]" /> 

Having said that, you mention about keeping restrict elements if they are not nested in a restrict element or within an element that does not have the restrict="restrict" attribute. In this case, the templates may need to look like this:

<xsl:template match="@restrict[../ancestor::restrict or ../ancestor::*[@restrict='restrict']]" />
<xsl:template match="restrict[ancestor::restrict or ancestor::*[@restrict='restrict']]" /> 

Try this XSLT

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@* | node()">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="@restrict[../ancestor::restrict or ../ancestor::*[@restrict='restrict']]" />        
    <xsl:template match="restrict[ancestor::restrict or ancestor::*[@restrict='restrict']]" /> 
</xsl:transform>
Tim C
  • 70,053
  • 14
  • 74
  • 93
  • Thank you for your explanation and assistance. I truly appreciate your help. This XSLT does mostly what I want, but it removes the restrict attribute from the first subsection1 that is not nested within a restrict. – 123CSRPIN Dec 04 '14 at 14:41
  • I've amended my answer to handle this situation. – Tim C Dec 04 '14 at 15:00
  • I just tried the amended answer, but the restrict attribute is still removed. It is odd because there aren't any restrict attributes set on the ancestors and it isn't contained within a restrict element, so why would it be stripped? – 123CSRPIN Dec 04 '14 at 15:14
  • 1
    Would it be possible to edit your question to re-format the XML to make it bit more readable, so it is easier to see where the attributes are? I also noticed your XSLT refers to a namespace (irs). Does you XML actually use namespaces in reality? Thanks! – Tim C Dec 04 '14 at 15:23
  • I see the issue now! I've updated my answer accordingly – Tim C Dec 04 '14 at 16:03
  • Wow! Thanks. This takes care of the subsection1 attribute. However, when I run it against my documents, I am seeing that restrict elements nested inside of p elements that are nested inside of a subsection1 with a restrict attribute are not being removed. I thought they would be because of the "ancestor::*[@restrict='restrict']" match? – 123CSRPIN Dec 05 '14 at 13:14
  • Are you sure they are nested and not siblings? Can you perhaps edit your question to include another example? Thanks! – Tim C Dec 05 '14 at 13:24
  • My apologies. It was my application. I used a different processor and it worked! Thank you so much for all of your help. As mentioned, this is all new to me. I am slowly learning, but I think that getting some training would do me well. – 123CSRPIN Dec 05 '14 at 14:49
0

If I understand this correctly, you want to do:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- remove the attribute restrict="restrict" if the attribute is nested within an element that also contains an attribute restrict="restrict". -->
<xsl:template match="@restrict[.='restrict'][parent::*/ancestor::*/@restrict='restrict']"/>


<!-- remove the element restrict if it is nested within an element containing an attribute restrict="restrict".  -->
<xsl:template match="restrict[ancestor::*/@restrict='restrict']">
    <xsl:apply-templates select="@*|node()"/>
</xsl:template>

</xsl:stylesheet>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Thank you. This is almost what I am looking for. I also need to remove the restrict element if it appears within another restrict element. Additionally, when I run this against my xml, the restrict element nested in a p nested in a subsection1 with a restrict attribute is not being removed. – 123CSRPIN Dec 05 '14 at 13:20
  • As I mentioned above, the restrict element, nested in a p, nested in a subsection1 with a restrict attribute was removed when I used a different processor. Thank you for your help. – 123CSRPIN Dec 05 '14 at 14:51
  • I am sorry, I don't really follow the nuances. I think you have the basis to make the necessary changes yourself, though. – michael.hor257k Dec 05 '14 at 16:20