GithubHelp home page GithubHelp logo

Comments (6)

jkowalleck avatar jkowalleck commented on September 7, 2024

did you consider configuring your project so that this one bom.xml file uses 2 spaces, regardless of the other configs?
your editor might even support EditorConfig which makes this possible with ease.

from cyclonedx-php-library.

jkowalleck avatar jkowalleck commented on September 7, 2024

Relevant API:

/**
* Serialize a {@see realNormalize() normalized} version of a {@see \CycloneDX\Core\Models\Bom}.
*
* @param TNormalizedBom $normalizedBom a version of the Bom that was normalized for serialization
*
* @throws Exception
*
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
*/
abstract protected function realSerialize(/* TNormalizedBom */ $normalizedBom, ?bool $prettyPrint): string;
// no typehint for `$normalizedBom` parameter, as it is not actually `mixed` but a templated type.

from cyclonedx-php-library.

jkowalleck avatar jkowalleck commented on September 7, 2024

i think the regex solution is potentially dangerous. it could add unwanted spaces in here:

<!--- [...] -->
<description>
  <![CDATA[the text in here is free to 
  write whatever they want, without escaping...
including XML special chars like the following
  <-- this line is possible and starts with an `<`

Depending on the definition of `description` in an XSD adding spaces here can change the content.
`xs:normalizedString` VS `xs:string` - see https://www.w3schools.com/XML/schema_dtypes_string.asp

  ]]>
</description>
<!--- [...] -->

I did not use XMLWriter when I implemented XML serialization, because I wanted typed return values for the normalizer. Therefore, I did not want to create a wrapper-Class just to represent the capabilities of an XML element, which already existed in PHP as a class, and can be serialized via libXML already.


I actually considered having a configurable amount of spaces when serializing.
The goal was just not worth the effort and trade-offs.
Furthermore, the amount of spaces does not change the quality of the document, so I skipped this feature.
I thought: if anybody wanted an alternative amount of spaces, then they could use external JSON/XML document reformatters that are feature-complete and work perfect in their domain.

from cyclonedx-php-library.

llaville avatar llaville commented on September 7, 2024

I propose to add (as last alternative) a tidy optional process.

Here are an example of my implementation :

<?php

namespace Bartlett\Manifests\Helper;

use CycloneDX\Core\Serialization\XmlSerializer;
use CycloneDX\Core\Serialization\DOM\NormalizerFactory;

class ManifestSerializer extends XmlSerializer
{
    protected readonly array $tidyConfig;

    public function __construct(
        NormalizerFactory $normalizerFactory,
        private string $xmlVersion = '1.0',
        private string $xmlEncoding = 'UTF-8',
        protected bool $withTidyRepair = true
    ) {
        parent::__construct($normalizerFactory, $xmlVersion, $xmlEncoding);

        $this->setTidyConfig(
            array(
                'input-xml' => true,
                'indent-attributes' => false,
                'wrap' => false,
                'indent-cdata' => true,
                'indent' => true,
                'indent-spaces' => 4
            )
        );
    }

    public function setTidyConfig(array $config)
    {
        $this->tidyConfig = $config;
    }

    protected function realSerialize(/* TNormalizedBom */ $normalizedBom, ?bool $prettyPrint): string
    {
        $document = new \DOMDocument($this->xmlVersion, $this->xmlEncoding);
        $document->appendChild(
            $document->importNode(
                $normalizedBom,
                true
            )
        );

        if (null !== $prettyPrint) {
            $document->formatOutput = $prettyPrint;
        }

        // option LIBXML_NOEMPTYTAG might lead to errors in consumers, do not use it.
        $xml = $document->saveXML();
        \assert(false !== $xml);


        if (!$this->withTidyRepair) {
            return $xml;
        }

        $clean = \tidy::repairString(
            $xml,
            $this->tidyConfig
        );

        if (\is_string($clean)) {
            return $clean;
        }

        // fallback to original version
        return $xml;
    }
}

And (example) results without tidy repair :

<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1" serialNumber="urn:uuid:4ee86da4-a5ef-4654-be46-0481c8f9080d">
  <metadata>
    <timestamp><![CDATA[2023-05-31T14:22:23Z]]></timestamp>
    <tools>
      <tool>
        <vendor><![CDATA[bartlett]]></vendor>
        <name><![CDATA[manifests]]></name>
        <version><![CDATA[dev-master]]></version>
      </tool>
    </tools>
  </metadata>
  <components>
    <component type="library" bom-ref="pkg:composer/clue/[email protected]">
      <group><![CDATA[clue]]></group>
      <name><![CDATA[graph-composer]]></name>
      <version><![CDATA[v1.1.0]]></version>
      <purl><![CDATA[pkg:composer/clue/[email protected]]]></purl>
      <properties>
        <property name="cdx:composer:package:sourceReference"><![CDATA[eff70fe2af7704b15cf675fcad663abe42034153]]></property>
        <property name="cdx:composer:package:distReference"><![CDATA[eff70fe2af7704b15cf675fcad663abe42034153]]></property>
        <property name="cdx:composer:package:isDevRequirement"><![CDATA[false]]></property>
      </properties>
    </component>
  </components>
  <dependencies>
    <dependency ref="pkg:composer/clue/[email protected]"/>
  </dependencies>
</bom>

And (example) results with tidy repair :

<?xml version="1.0" encoding="utf-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1" serialNumber="urn:uuid:39b92711-c69b-448f-9d51-f68135735507">
    <metadata>
        <timestamp>
            <![CDATA[2023-05-31T14:15:47Z]]>
        </timestamp>
        <tools>
            <tool>
                <vendor>
                    <![CDATA[bartlett]]>
                </vendor>
                <name>
                    <![CDATA[manifests]]>
                </name>
                <version>
                    <![CDATA[dev-master]]>
                </version>
            </tool>
        </tools>
    </metadata>
    <components>
        <component type="library" bom-ref="pkg:composer/clue/[email protected]">
            <group>
                <![CDATA[clue]]>
            </group>
            <name>
                <![CDATA[graph-composer]]>
            </name>
            <version>
                <![CDATA[v1.1.0]]>
            </version>
            <purl>
                <![CDATA[pkg:composer/clue/[email protected]]]>
            </purl>
            <properties>
                <property name="cdx:composer:package:sourceReference">
                    <![CDATA[eff70fe2af7704b15cf675fcad663abe42034153]]>
                </property>
                <property name="cdx:composer:package:distReference">
                    <![CDATA[eff70fe2af7704b15cf675fcad663abe42034153]]>
                </property>
                <property name="cdx:composer:package:isDevRequirement">
                    <![CDATA[false]]>
                </property>
            </properties>
        </component>
    </components>
    <dependencies>
        <dependency ref="pkg:composer/clue/[email protected]" />
    </dependencies>
</bom>

from cyclonedx-php-library.

llaville avatar llaville commented on September 7, 2024

BTW, when class is not marked as final, I'd like to have protected visibility to properties. That will avoid inheritance issue !

from cyclonedx-php-library.

jkowalleck avatar jkowalleck commented on September 7, 2024

tidy is not part of PHP core.
Introducing this as a dependency would be a breaking change.

from cyclonedx-php-library.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.