I want to use xmlstarlet from the powershell started with Process in a C# application.
My main problem is that when I use this code:
./xml.exe ed -N ns=http://www.w3.org/2006/04/ttaf1 -d '//ns:div[not(contains(#xml:lang,''Italian''))]' "C:\Users\1H144708H\Downloads\a.mul.ttml" > "C:\Users\1H144708H\Downloads\a.mul.ttml.conv"
on powershell I get a file with the wrong encoding (I need UTF-8).
On Bash I used to just
export LANG=it_IT.UTF-8 &&
before xmlstarlet but on powershell I really don't know how to do it.
Maybe there is an alternative, I saw that xmlstarlet is able to use sel --encoding utf-8 but I don't know how to use it in ed mode (I tried to use it after xml.exe after ed etc... but it always fail).
What is the alternative to export LANG=it_IT.UTF-8 or how to use --encoding utf-8?
PS. I tried many and many things like:
$MyFile = Get-Content "C:\Users\1H144708H\Downloads\a.mul.ttml"; $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False; [System.IO.File]::WriteAllLines("C:\Users\1H144708H\Downloads\a.mul.ttml.conv", $MyFile, $Utf8NoBomEncoding)
And:
./xml.exe ed -N ns=http://www.w3.org/2006/04/ttaf1 -d '//ns:div[not(contains(#xml:lang,''Italian''))]' "C:\Users\1H144708H\Downloads\a.mul.ttml" | Out-File "C:\Users\1H144708H\Downloads\a.mul.ttml.conv" -Encoding utf8
But characters like è à ì ù are still wrong. If I try to save the original file with Notepad before the conversion it works (only if I don't use xmlstarlet)... but I need to do the same thing in powershell and I don't know how.
EDIT.
I was able to print my utf8 on powershell:
Get-Content -Path "C:\Users\1H144708H\Downloads\a.mul.ttml" -Encoding UTF8
But I'm still not able to do the same thing with xmlstarlet.
In the end I decided to create a native C# method and I just used a StreamReader to ReadLine by line the file. With a simple Contains I decide where is the xml:lang="Language" and I then start to add every line to a string. Of course I added the head and the end of my file before the while loop and I stop to add every line when I read a line that Contains . I know that this is not the best way to do things, but it works for my case.
Related
Could someone help me understand the behaviour of the makefile, below? To give some context, I am trying to generated a series of c# classes from a set of .proto files. The proto files are contained within a directory structure which i want to mirror in the output. So, assuming my source files are in a folder called 'Source' and I am outputting into a folder called 'Generated', if a file resides in:
'Source/Foo/Bar/myfile.protoc'
then output should be:
'Generated/Foo/Bar/MyFile.cs'.
This seems simple enough however I am seeing some strange behaviour when using dir/notdir in the make file. here is an example:
# Makefile to build message definitions within this repo
PROTOS:= SourceFiles/Module_1/BasicMessage.proto SourceFiles/Module_2/BasicMessage.proto
withVariables:
for proto in $(PROTOS) ; do \
echo $(dir $$proto) ; \
echo $(notdir $$proto) ; \
done;
hardCoded:
echo $(dir ./SourceFiles/Module_1/BasicMessage.proto)
echo $(notdir ./SourceFiles/Module_1/BasicMessage.proto)
echo $(dir ./SourceFiles/Module_2/BasicMessage.proto)
echo $(notdir ./SourceFiles/Module_2/BasicMessage.proto)
Essentially, when I have the collection of file names in a variable and try to iterate them, dir/notdir does not seem to recognised the separators in the path. Running Make hardCoded here gives:
./SourceFiles/Module_1/
BasicMessage.proto
./SourceFiles/Module_2/
BasicMessage.proto
which is what i would expect. However, running withVariables gives:
./
SourceFiles/Module_1/BasicMessage.proto
./
SourceFiles/Module_2/BasicMessage.proto
I am still pretty new to make files, so I am probably missing something simple, but if anyone can explain why these two examples behave differently, it would be greatly appreciated.
The recipes are expanded by make before being passed to the shell. So, in the recipe of withVariables, the $(dir $$proto) and $(notdir $$proto) are expanded to ./ and $proto, respectively. The recipe becomes:
for proto in SourceFiles/Module_1/BasicMessage.proto SourceFiles/Module_2/BasicMessage.proto; do \
echo ./ ; \
echo $proto ; \
done;
which logically produces the output you see. You cannot use make functions in your recipes and expect them to be executed by the shell. Instead you can invoke the standard dirname and basename external programs from your recipe:
withVariables:
for proto in $(PROTOS); do \
echo $$(dirname $$proto); \
echo $$(basename $$proto); \
done
The recipe is expanded by make as:
for proto in SourceFiles/Module_1/BasicMessage.proto SourceFiles/Module_2/BasicMessage.proto; do \
echo $(dirname $proto); \
echo $(basename $proto); \
done
which, when executed by the shell, outputs:
host> make withVariables
SourceFiles/Module_1
BasicMessage.proto
SourceFiles/Module_2
BasicMessage.proto
I need to programmatically get the last author of a specific line in the Git history with C#.
I tried using libgit2sharp :
var repo = new LibGit2Sharp.Repository(gitRepositoryPath);
string relativePath = MakeRelativeSimple(filename);
var blameHunks = repo.Blame(relativePath);
// next : find the hunk which overlap the desired line number
But this is the equivalent of the command
git blame <file>
And in fact I need
git blame -w <file> (to ignore whitespace when comparing)
Libgit2sharp do not set the -w switch and don't provide any parameter/option to set it.
What are my options ? Do you know any other library compatible with the -w switch of the blame command ?
When I hit similar advanced scenarios where the git lib isn't cutting it, I just shell out using start process to the real git command line. It's not sexy, but it's mighty effective.
Maybe using NGIT library will help. That is direct (automatic) port of java JGIT library. Install via nuget package, then:
static void Main() {
var git = Git.Init().SetDirectory("C:\\MyGitRepo").Call();
string relativePath = "MyFolder/MyFile.cs";
var blameHunks = git.Blame().SetFilePath(relativePath).SetTextComparator(RawTextComparator.WS_IGNORE_ALL).Call();
blameHunks.ComputeAll();
var firstLineCommit = blameHunks.GetSourceCommit(0);
// next : find the hunk which overlap the desired line number
Console.ReadKey();
}
Note SetTextComparator(RawTextComparator.WS_IGNORE_ALL) part.
Unfortunately, libgit2sharp is too slow on extracting blames and using this feature is impractical in real scenarios. So, the best way I think is to employ a Powershell script to use the underlying superfast native git. And then redirect the result to your application.
git blame -l -e -c {commit-sha} -- "{file-path}" | where { $_ -match '(?<sha>\w{40})\s+\(<(?<email>[\w\.\-]+#[\w\-]+\.\w{2,3})>\s+(?<datetime>\d\d\d\d-\d\d-\d\d\s\d\d\:\d\d:\d\d\s-\d\d\d\d)\s+(?<lineNumber>\d+)\)\w*' } |
foreach { new-object PSObject –prop #{ Email = $matches['email'];lineNumber = $matches['lineNumber'];dateTime = $matches['dateTime'];Sha = $matches['sha']}}
I have a C# assembly that processes an xml file and at the end spits out the results to the console.
e.g. Console.WriteLine(_header.ToString());
I can load this dll in powershell and call the right method like this:
[sqlproj_doctor.sqlprojDoctor]::ProcessXML($file) | out-file ./test.xml
All is well.
The problem begins when I want to redirect the output. For some reason stdout is empty. What am I missing? I need to be further process the output of this dll.
Note: If I compile the same code as an executable, it correctly populates the standard output stream and I can redirect the output.
another note: as a workaround, I changed the method from void to string, and can now manipulate the returned string.
When you call [Console]::WriteLine('SomeText'), it write to PowerShell process stdout, not to command output, and so it can not be redirected from inside same PowerShell process, by standard PowerShell operators, like this:
[Console]::WriteLine('SomeText')|Out-File Test.txt
You have to spawn new PowerShell process, and redirect output of that new process:
powershell -Command "[Console]::WriteLine('SomeText')"|Out-File Test.txt
In case if some command use [Console]::WriteLine to write to console, you can capture that output without starting new PowerShell instance:
$OldConsoleOut=[Console]::Out
$StringWriter=New-Object IO.StringWriter
[Console]::SetOut($StringWriter)
[Console]::WriteLine('SomeText') # That command will not print on console.
[Console]::SetOut($OldConsoleOut)
$Results=$StringWriter.ToString()
$Results # That variable would contain "SomeText" text.
Although this does not help if command does not use [Console]::WriteLine, but write to stdout stream directly:
$OldConsoleOut=[Console]::Out
$StringWriter=New-Object IO.StringWriter
[Console]::SetOut($StringWriter)
$Stdout=[Console]::OpenStandardOutput()
$Bytes=[Console]::OutputEncoding.GetBytes("SomeText"+[Environment]::NewLine)
$Stdout.Write($Bytes,0,$Bytes.Length) # That command will print on console.
$Stdout.Close()
[Console]::SetOut($OldConsoleOut)
$Results=$StringWriter.ToString()
$Results # That variable will be empty.
I am having an issue with the spaces in my command. I am trying to run the cmd prompt and execute a program that takes command line arguments. I need the cmd window to remain open after the process is finished executing.
I managed to get it working in another section of code, but this time i am almost sure it has to do with the spaces in the path of the argument. If i use a path with no spaces, it works fine. I tried to escape the quotes, but either i am doing it incorrectly, or escaping the quotes do not work.
Basically, I need to make the line below work with spaces and keep the cmd window open after the execution...
Dim ps As Process = System.Diagnostics.Process.Start("cmd /k", "C:\common\tools\tap.exe -f flash C:\Users\test project\Desktop\image.signed")
I'm know the space between "test" and "project" is the issue, but i haven't been able to get around it.
Thanks in advance for your help.
Wrap the path in double-quotes, like this:
"C:\common\tools\tap.exe -f flash ""C:\Users\test project\Desktop\image.signed"""
Giving you:
Dim ps As Process = System.Diagnostics.Process.Start ("cmd /k", "C:\common\tools\tap.exe -f flash ""C:\Users\test project\Desktop\image.signed""")
I have created a .NET C# project that I have commented using blocks similar to ///<summary>A summary...</summary> that I would like to document using Doxygen. I have set up Doxygen and it runs generating a some 100 .tex-files and a Makefile.
As I have understood, the Makefile is the key to generating the documentation as a PDF, however I do not get it to work.
I'm using a Mac to do the LaTeX and Doxygen bit by writing make -f Makefile in the Terminal when I am in the Doxygen LaTeX output directory.
all: refman.pdf
pdf: refman.pdf
refman.pdf: clean refman.tex
pdflatex refman
makeindex refman.idx
pdflatex refman
latex_count=5 ; \
while egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\
do \
echo "Rerunning latex...." ;\
pdflatex refman ;\
latex_count=`expr $$latex_count - 1` ;\
done
clean:
rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf
When running, i get the following message:
MacBook-Pro-13:latex sehlstrom$ make
rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf
make: *** No rule to make target `refman.tex', needed by `refman.pdf'. Stop.
How can I get the Makefil thing work?
refman.tex is supposed to be created by Doxygen. I just tested with my installed version, doxygen 1.7.2, and it created a refman.tex.
Make sure you aren't setting any option that says this is a component of a larger project that shouldn't have its own index.