Home > Software engineering >  XSLT: Add entire input XML to output in normalized space text format
XSLT: Add entire input XML to output in normalized space text format

Time:08-24

I am working on an XSLT to transform an input XML into a JSON object. The last thing that is confusing me is I've been asked to put the input XML as an attribute to the output. I've seen other solutions that say to use <xsl:copy-of select="." />. When I have <xsl:output method="text" />, it just prints a bunch of junk like when I was having trouble with namespaces. When I have <xsl:output method="xml" />, it works, but then I have <?xml version="1.0" encoding="UTF-8"?> at the top of my output file, which I don't want. Plus, it would be nice if I could call normalized-space on the output so I could get rid of all the indentation/new lines.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:uswx="http://nws.weather.gov/schemas/USWX/1.0"
                xmlns:xlink="http://www.w3.org/1999/xlink"
                xmlns:metce="http://def.wmo.int/metce/2013"
                xmlns:om="http://www.opengis.net/om/2.0"
                xmlns:gml="http://www.opengis.net/gml/3.2"
                exclude-result-prefixes="uswx">
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/>
    <xsl:template match="/">{
    "input": "<xsl:copy-of select="." />"
}
    </xsl:template>

Input

<?xml version="1.0" encoding="UTF-8"?>
<G-AIRMET gml:id="uuid.b3a1b430-b8e0-4943-abb7-796b9a802c49"
    xmlns="http://nws.weather.gov/schemas/USWX/1.0"
    xmlns:aixm="http://www.aixm.aero/schema/5.1.1"
    xmlns:gml="http://www.opengis.net/gml/3.2"
    xmlns:metce="http://def.wmo.int/metce/2013"
    xmlns:om="http://www.opengis.net/om/2.0"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://nws.weather.gov/schemas/USWX/1.0 http://nws.weather.gov/schemas/USWX/1.0/G-Airmet.xsd">
    <airmetStatus
        xlink:href="https://codes.nws.noaa.gov/NWSI-10-811/ProductStatus/Normal"
        xlink:title="Normal"></airmetStatus>
    <productDescription
        xlink:href="http://codes.nws.weather.gov/NWSI-10-811/AirmetProductDescription/SIERRA"
        xlink:title="SIERRA"></productDescription>
    <airmetSeries
        xlink:href="http://codes.nws.weather.gov/NWSI-10-811/AirmetSeries/S"
        xlink:title="S"></airmetSeries>
    <forecastArea>KCI</forecastArea>
</G-AIRMET>

Output

{
    "input": "<?xml version="1.0" encoding="UTF-8"?><G-AIRMET gml:id="uuid.b3a1b430-b8e0-4943-abb7-796b9a802c49" xmlns="http://nws.weather.gov/schemas/USWX/1.0" xmlns:aixm="http://www.aixm.aero/schema/5.1.1" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:metce="http://def.wmo.int/metce/2013" xmlns:om="http://www.opengis.net/om/2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nws.weather.gov/schemas/USWX/1.0 http://nws.weather.gov/schemas/USWX/1.0/G-Airmet.xsd"> <airmetStatus   xlink:href="https://codes.nws.noaa.gov/NWSI-10-811/ProductStatus/Normal" xlink:title="Normal"></airmetStatus> <productDescription xlink:href="http://codes.nws.weather.gov/NWSI-10-811/AirmetProductDescription/SIERRA" xlink:title="SIERRA"></productDescription> <airmetSeries xlink:href="http://codes.nws.weather.gov/NWSI-10-811/AirmetSeries/S" xlink:title="S"></airmetSeries> <forecastArea>KCI</forecastArea> </G-AIRMET>"
}

CodePudding user response:

Try perhaps:

XSLT 1.0

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

<xsl:template match="/">
    <xsl:text >{
    "input": "</xsl:text>
    <xsl:copy-of select="." />
    <xsl:text >"
}</xsl:text>
</xsl:template>

</xsl:stylesheet>

it would be nice if I could call normalized-space on the output so I could get rid of all the indentation/new lines.

That's not possible using this method, because the data passed to the output is not a string. If you want to control how the input tree is serialized when passed to the output, you must do your own serialization - using either XSLT 3.0 or possibly http://lenzconsulting.com/xml-to-string/.

CodePudding user response:

XSLT 3.0 allows you to create JSON output:

<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0">
  
  <xsl:output method="json" indent="yes" use-character-maps="jsonChars" />
  
  <xsl:character-map name="jsonChars" >
    <xsl:output-character character="/" string="/" />
  </xsl:character-map>

  <xsl:template match="/" name="xsl:initial-template">
      <xsl:map-entry key="'input'" select="serialize(/)" />
  </xsl:template>
  
</xsl:stylesheet>

which produces:

{
   "input": "<G-AIRMET xmlns:aixm=\"http://www.aixm.aero/schema/5.1.1\" xmlns:gml=\"http://www.opengis.net/gml/3.2\" xmlns:metce=\"http://def.wmo.int/metce/2013\" xmlns:om=\"http://www.opengis.net/om/2.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://nws.weather.gov/schemas/USWX/1.0\" gml:id=\"uuid.b3a1b430-b8e0-4943-abb7-796b9a802c49\" xsi:schemaLocation=\"http://nws.weather.gov/schemas/USWX/1.0 http://nws.weather.gov/schemas/USWX/1.0/G-Airmet.xsd\">\n    <airmetStatus xlink:href=\"https://codes.nws.noaa.gov/NWSI-10-811/ProductStatus/Normal\" xlink:title=\"Normal\"/>\n    <productDescription xlink:href=\"http://codes.nws.weather.gov/NWSI-10-811/AirmetProductDescription/SIERRA\" xlink:title=\"SIERRA\"/>\n    <airmetSeries xlink:href=\"http://codes.nws.weather.gov/NWSI-10-811/AirmetSeries/S\" xlink:title=\"S\"/>\n    <forecastArea>KCI</forecastArea>\n</G-AIRMET>"
}
  • Related