XML refactoring to move attribute value to a new attribute/element

Post here questions and problems related to editing and publishing DITA content.
pbentley
Posts: 3
Joined: Mon Sep 19, 2022 11:39 pm

XML refactoring to move attribute value to a new attribute/element

Post 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
Radu
Posts: 8283
Joined: Fri Jul 09, 2004 5:18 pm

Re: XML refactoring to move attribute value to a new attribute/element

Post 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
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
chrispitude
Posts: 652
Joined: Thu May 02, 2019 2:32 pm

Re: XML refactoring to move attribute value to a new attribute/element

Post by chrispitude »

Hi Peyton,

Can you provide an example of the input and output you would like to see?
pbentley
Posts: 3
Joined: Mon Sep 19, 2022 11:39 pm

Re: XML refactoring to move attribute value to a new attribute/element

Post 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!!
chrispitude
Posts: 652
Joined: Thu May 02, 2019 2:32 pm

Re: XML refactoring to move attribute value to a new attribute/element

Post 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?
pbentley
Posts: 3
Joined: Mon Sep 19, 2022 11:39 pm

Re: XML refactoring to move attribute value to a new attribute/element

Post 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!
chrispitude
Posts: 652
Joined: Thu May 02, 2019 2:32 pm

Re: XML refactoring to move attribute value to a new attribute/element

Post by chrispitude »

Hi Peyton,

First, you need a template to remove the @id attribute from the <p> element:

Code: Select all

  <xsl:template match="p/@id"/>
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.
Post Reply