Data-Edit-Xml-Xref

 view release on metacpan or  search on metacpan

lib/Data/Edit/Xml/Xref.pm  view on Meta::CPAN

          </folder>
          <folder name="Images">
            $images
          </folder>
          <folder name="Resources">
            $resources
          </folder>
          <folder name="Topics">
            $topics
          </folder>
        </folder>
        <folder name="CCX Content Repo (All)">
           <folder path="../"/>
        </folder>
    </projectTree>
</project>
END

# $X->go_projectTree->last->by(sub                                              # Cut out empty folders under the last folder otherwise we get lots of empty folders that contain no files because the files in them were not relevant to this bookmap
#  {my ($f) = @_;
#   $f->cutIfEmpty_folder;
#  });

  if ($@)
   {cluck "Unable to parse generated oxygen project file:\n$@"
   }
  else
   {my $text = Data::Edit::Xml::xmlHeader -p $X;

    owf($out, $text);
   }
 } # createOxygenProjectFile

sub createOxygenProjectMapFiles($)                                              #P Create Oxygen project files from Xref results
 {my ($xref) = @_;                                                              # Cross referencer

  my $xprName = sub                                                             # Method of choosing xpr file name
   {my $x = $xref->oxygenProjects;                                              # Method specified by caller
    if (isSubInPackage(q(Data::Edit::Xml::Xref), q(xprName)))
     {return sub {&Data::Edit::Xml::Xref::xprName(@_)}                          # Call supplied sub to generate xpr file name
     }
    return sub {my ($bm) = @_; setFileExtension($bm, q(xpr))} unless ref $x;    # xpr file mirrors book map
   }->();

  processFilesInParallel
    sub
     {my ($bm) = @_;
      createOxygenProjectFile($xref, $bm, $xprName);
     },
    sub {}, sort keys $xref->exteriorMaps->%*;                                  # Only for exterior book maps - i.e. only book maps that not referenced by any other book map.

  {}                                                                            # Multiverse to universe
 } # createOxygenProjectMapFiles

sub oneBadRef($$$)                                                              #P Check one reference and return the first error encountered or B<undef> if no errors encountered. Relies on L<topicIds> to test files present and test the B<topicId> is...
 {my ($xref, $file, $href) = @_;                                                # Cross referencer, file containing reference, reference

  my $fileExists = sub                                                          # Check that the specified file exists by looking for the topic id which L<Dita> guarantees will exist
   {my ($file) = @_;                                                            # File to check
    return 1 if $xref->topicIds->{$file};                                       # File exists
    my $decodedTarget = wwwDecode($file);                                       # Decode file name by expanding % signs to see if we can get a match
    return 2 if $xref->topicIds->{$decodedTarget};                              # File exists after decoding % signs
    return 3 if -e $file;                                                       # Images
    undef                                                                       # Cannot locate file
   };

  if ($href =~ m(#))                                                            # Full Dita href
   {my $sourceTopicId = $xref->topicIds->{$file};                               # Source id for referencing file
    my ($target, $topicId, $id) = parseDitaRef($href, $file, $sourceTopicId);   # Parse full Dita href
    my $targetFile    = absFromAbsPlusRel($file, $target//$file);               # Absolute target file which might be the current file
    my $targetTopicId = $xref->topicIds->{$targetFile};                         # Topic Id of target file

    my $bad = sub                                                               # Report a bad reference
     {my ($r) = @_;                                                             # Reason
       [$r, $href, $target, $topicId, $id, $sourceTopicId,
        $targetTopicId, $file, $targetFile];
     };

    return &$bad(q(No such file)) unless &$fileExists($targetFile);             # Check target file exists
    return &$bad(q(No topic id))  unless $targetTopicId;                        # Check the target has a topic id
    return &$bad(q(Topic id does not match))
      unless $targetTopicId eq $topicId or $topicId eq q();                     # Check topic id of referenced topic against supplied topicId.  It is safe to assume that the target does have topic id as Dita requires one

    if ($id)                                                                    # Checkid if supplied
     {my $i = $xref->ids->{$target}{$id};                                       # Number of ids in the target topic with this value
      return &$bad(q(No such id in target topic)) unless $i;                    # No such id
      return &$bad(q(Duplicated id in target topic))                            # Duplicate ids
        unless $i == 1 or $i == 2 && $id eq $topicId;                           # Using dita topic references we can cope with one internal id that duplicates the topic id
     }
   }

  else                                                                          # No # in href
   {my $targetFile = absFromAbsPlusRel($file, $href);
    return [q(No such file), $href, $href, q(), q(), q(), q(),
            $file, $targetFile] unless &$fileExists($targetFile);               # Check target file exists
   }

  undef                                                                         # No error to report
 } # oneBadRef

#D0
# podDocumentation
=pod

=encoding utf-8

=head1 Name

Data::Edit::Xml::Xref - Cross reference Dita XML, match topics and ameliorate missing references.

=head1 Synopsis

L<Xref> scans an entire document corpus looking primarily for problems with
references between the files in the corpus; it reports any opportunities for
improvements it finds and makes changes to the corpus to implement these
improvements if so requested taking advantage of parallelism where ever
possible.

The following example checks the references in a corpus of Dita XML
documents held in folder L<inputFolder|/inputFolder>:

  use Data::Edit::Xml::Xref;



( run in 1.562 second using v1.01-cache-2.11-cpan-995e09ba956 )