Page 1 of 1
XML refactoring to move attribute value to a new attribute/element
Posted: Mon Sep 19, 2022 11:42 pm
by pbentley
Hi there,
Is there a way that I can use XML Refactoring to move an attribute value to a different attribute and element?
I have a value like this: <p id="section_2100.502">
but I need to move it to here: <resourceid appid="section_2100.502" appname="legacy-id"/>
I've looked at the refactoring files but can't figure out how to accomplish this so any help would be great appreciated!
Thanks!
Peyton
Re: XML refactoring to move attribute value to a new attribute/element
Posted: Tue Sep 20, 2022 8:24 am
by Radu
Hi Peyton,
We do not have a predefined XML refactoring action to do exactly what you want.
You can implement your own custom XML refactoring actions based on XSLT or XQuery scripts:
https://www.oxygenxml.com/doc/versions/ ... tools.html
We have a bunch of sample XML refactoring actions based on XSLT here:
https://github.com/oxygenxml/dita-refactoring-examples
For example an XSLT stylesheet for an XML refactoring operation doing something similar to what you want could look like this:
Code: Select all
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="prolog">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()"/>
<xsl:if test="//*[starts-with(@id, 'section_')]">
<resourceid appid="{//*[starts-with(@id, 'section_')]/@id}" appname="legacy-id"/>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Regards,
Radu
Re: XML refactoring to move attribute value to a new attribute/element
Posted: Tue Sep 20, 2022 12:52 pm
by chrispitude
Hi Peyton,
Can you provide an example of the input and output you would like to see?
Re: XML refactoring to move attribute value to a new attribute/element
Posted: Tue Sep 20, 2022 4:08 pm
by pbentley
Thanks, Radu! I'll look into that page.
I'm doing a whole series of refactoring combined with find/replaces but for this particular step, I'd have something like this as my input:
<body>
<p id="section_2100.502">
<b>Accountability
(accountable).</b>
</p>
<prolog>
<resourceid appid="" appname="legacy-id"/>
</prolog>
</body>
and I'd want to see this as the output:
<body>
<p id="">
<b>Accountability
(accountable).</b>
</p>
<prolog>
<resourceid appid="section_2100.502" appname="legacy-id"/>
</prolog>
</body>
Essentially just moving the id from the p down to the resourceid appid.
Thanks!!
Re: XML refactoring to move attribute value to a new attribute/element
Posted: Tue Sep 20, 2022 4:50 pm
by chrispitude
Hi Peyton,
In DITA, the <prolog> element should be before the <body> element. Can you confirm that is true in your content?
Will there only be a single <p> element with an @id defined, or could there be multiple such <p> elements?
Will all topics have an existing <prolog> element? Or will some topics have no <prolog> element, such that they will need to be created by the refactoring operation?
Re: XML refactoring to move attribute value to a new attribute/element
Posted: Tue Sep 20, 2022 7:56 pm
by pbentley
Hi chrispitude,
Yes, the structure is right, with <prolog> following body. This is currently a specialized topic file that I'm refactoring to become a glossary file, so at this point in my refactoring/adjusting, the body is still there (but it will eventually get dropped/changed).
Each file will have only one <p> and I added the <prolog> manually to each file (with an empty value for the appid) so no need for the refactoring to add it.
Thank you!
Re: XML refactoring to move attribute value to a new attribute/element
Posted: Wed Sep 21, 2022 5:26 am
by chrispitude
Hi Peyton,
First, you need a template to remove the
@id attribute from the <p> element:
To leave @id set to a blank value as you asked (which is not valid XML!)!, then you would do this:
Code: Select all
<xsl:template match="p/@id">
<xsl:attribute name="id" select="''"/>
</xsl:template>
Now you need a second template to place the
@id value where you want it. If you already have an empty
<prolog> element, then you can do something like this:
Code: Select all
<xsl:template match="prolog[preceding-sibling::p[@id]]">
<xsl:copy>
<resourceid appid="{preceding-sibling::p[@id][1]/@id}" appname="legacy-id"/>
</xsl:copy>
</xsl:template>
(The curly braces in an attribute value allow an XPath expression to be evaluated for the value.)
If some
<prolog> elements do not yet exist, or they do exist and contain other metadata, then some smarter templates would be needed to handle those cases too.