I am trying to parse the following xml using tiny xml parser.I am trying to get the value of all producer and consumer attributes of q2channel tag in the xml file.I am using tinyxml2.
So far I have written the following code but I am stuck here as when I try to print something I get null.
XMLDocument doc;
bool loadOkay=doc.LoadFile( "resources/q2profiling.xml" );
XMLElement* titleElement = doc.FirstChildElement()->FirstChildElement();
const char* title = titleElement->GetText();
printf( "The remaining xml is %s\n", title );
I have tried several different variations of the code to progress my work but I am stuck here.Please help me in printing the value of all consumer and producer attributes of q2channel tag from the xml.
The xml file is given below
<
?xml version="1.0" encoding="UTF-8" ?>
<q2:profiles xmlns:q2="http://www.example.org/q2profiling" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/q2profiling q2profiling.xsd">
<q2:application name="testAPPlication">
<q2:QDUGraph>
<q2:channel producer="UNKNOWN_PRODUCER(CONSTANT_DATA)" consumer="Out_of_the_main_function_scope">
<q2:UnMA>19298</q2:UnMA>
<q2:Bytes>25892</q2:Bytes>
<q2:UnDV>19298</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="134512692" upper="134512695" />
<q2:range lower="134512700" upper="134512703" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="UNKNOWN_PRODUCER(CONSTANT_DATA)" consumer="main">
<q2:UnMA>160</q2:UnMA>
<q2:Bytes>234</q2:Bytes>
<q2:UnDV>160</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="134513084" upper="134513087" />
<q2:range lower="134513116" upper="134513119" />
<q2:range lower="134513129" upper="134513129" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="Out_of_the_main_function_scope" consumer="Out_of_the_main_function_scope">
<q2:UnMA>1474</q2:UnMA>
<q2:Bytes>14815</q2:Bytes>
<q2:UnDV>2468</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="134520828" upper="134520831" />
<q2:range lower="134520836" upper="134520843" />
<q2:range lower="3077693172" upper="3077693175" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="Out_of_the_main_function_scope" consumer="main">
<q2:UnMA>209</q2:UnMA>
<q2:Bytes>381</q2:Bytes>
<q2:UnDV>209</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="134520836" upper="134520847" />
<q2:range lower="3045611784" upper="3045611795" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="main" consumer="Out_of_the_main_function_scope">
<q2:UnMA>40</q2:UnMA>
<q2:Bytes>60</q2:Bytes>
<q2:UnDV>40</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="3048639008" upper="3048639019" />
<q2:range lower="3048639024" upper="3048639031" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="main" consumer="main">
<q2:UnMA>32</q2:UnMA>
<q2:Bytes>444</q2:Bytes>
<q2:UnDV>88</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="3048639008" upper="3048639011" />
<q2:range lower="3048639016" upper="3048639019" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="UNKNOWN_PRODUCER(CONSTANT_DATA)" consumer="sum">
<q2:UnMA>1</q2:UnMA>
<q2:Bytes>1000</q2:Bytes>
<q2:UnDV>1</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="134520860" upper="134520860" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="UNKNOWN_PRODUCER(CONSTANT_DATA)" consumer="diff">
<q2:UnMA>1</q2:UnMA>
<q2:Bytes>1000</q2:Bytes>
<q2:UnDV>1</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="134520860" upper="134520860" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="init" consumer="sum">
<q2:UnMA>2000</q2:UnMA>
<q2:Bytes>2000</q2:Bytes>
<q2:UnDV>2000</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="134520896" upper="134521895" />
<q2:range lower="134523968" upper="134524967" />
</q2:UnMARanges>
</q2:channel>
<q2:channel producer="init" consumer="diff">
<q2:UnMA>2000</q2:UnMA>
<q2:Bytes>2000</q2:Bytes>
<q2:UnDV>2000</q2:UnDV>
<q2:UnMARanges>
<q2:range lower="134520896" upper="134521895" />
<q2:range lower="134523968" upper="134524967" />
</q2:UnMARanges>
</q2:channel>
</q2:QDUGraph>
</q2:application>
</q2:profiles>
The function GetText() won't give you the actual name of the node in question, but the text inside the node. For instance, invoking GetText() on this hypothetical node
<node>This is text!</node>
will yield "This is text!" as a const char* or a const std::string& depending on how you compile. See the API reference of TiXmlElement.
If you want to query the node name itself, use TiXmlNode::Value().
If you want an attribute, simply use Attribute(const char*) or QueryStringAttribute(...) on the element. For instance, retrieving and printing the following with the document you provided
std::cout << doc.FirstChildElement ()->FirstChildElement ()->Attribute ("name") << std::endl;
yields "testAPPlication".
In general, see the full documentation of TinyXML first.
EDIT: The following example depicts in a simple, yet ugly way what you need:
TiXmlDocument doc;
if(doc.LoadFile ("test.xml"))
{
TiXmlElement* graphElem = doc.FirstChildElement()->FirstChildElement ()->FirstChildElement ();
TiXmlElement* channelElem = graphElem->FirstChildElement ();
for(; channelElem; channelElem = channelElem->NextSiblingElement ())
{
std::cout << channelElem->Attribute ("producer")
<< " | "
<< channelElem->Attribute ("consumer")
<< std::endl;
}
}
EDIT2: Removed infinite loop and conditional.
Related
I'd like to replace all lines containing Test.bundle (those lines are grouped in one block) with other files
from
<ItemGroup>
<BundleResource Include="Resources\some_other_file.json" />
<BundleResource Include="Resources\Test.bundle\one.png" />
<BundleResource Include="Resources\Test.bundle\two.png" />
<BundleResource Include="Resources\Test.bundle\three.png" />
</ItemGroup>
to
<ItemGroup>
<BundleResource Include="Resources\some_other_file.json" />
<BundleResource Include="Resources\Test.bundle\four.png" />
<BundleResource Include="Resources\Test.bundle\five.png" />
<BundleResource Include="Resources\Test.bundle\six.png" />
<BundleResource Include="Resources\Test.bundle\seven.png" />
</ItemGroup>
What I did
res=$(find Resources/Test.bundle -type f | sed 's/\\/\//g' | xargs -I {} echo "<BundleResource Include=\"{}\" />") #get new files, change path delimiters, wrap file names in output pattern
sed -E -i '' '/Test\.bundle/,/ItemGroup/c\
BUNDLE_PLACEHOLDER' file.ext #remove whole block from first line containing Test.bundle to closing ItemGroup and replace with placeholder
sed -E -i '' "s:BUNDLE_PLACEHOLDER:$res:" file.ext #replace with new block
I couldn't change it in one pass in the third command due to "extra characters after \ at the end of c command" so I changed it to the string placeholder that I was trying to replace in the next command. That also failed due to unescaped newline inside substitute pattern that I'm currently trying to solve. There is also missing closing ItemGroup tag that will be added later.
Are there any other options using sed?
Can I catch only group containing Test.bundle without catching closing ItemGroup?
How to escape newlines to satisfy the substitution pattern?
It's not clear what you're really trying to match on but this might be what you want:
awk '
NR==FNR {
new = new $0 ORS
next
}
/Test\.bundle/ {
printf "%s", new
new = ""
next
}
{ print }
' new old
e.g.:
$ cat old
<ItemGroup>
<BundleResource Include="Resources\some_other_file.json" />
<BundleResource Include="Resources\Test.bundle\one.png" />
<BundleResource Include="Resources\Test.bundle\two.png" />
<BundleResource Include="Resources\Test.bundle\three.png" />
</ItemGroup>
$ cat new
<BundleResource Include="Resources\Test.bundle\four.png" />
<BundleResource Include="Resources\Test.bundle\five.png" />
<BundleResource Include="Resources\Test.bundle\six.png" />
<BundleResource Include="Resources\Test.bundle\seven.png" />
.
$ awk '
NR==FNR {
new = new $0 ORS
next
}
/Test\.bundle/ {
printf "%s", new
new = ""
next
}
{ print }
' new old
<ItemGroup>
<BundleResource Include="Resources\some_other_file.json" />
<BundleResource Include="Resources\Test.bundle\four.png" />
<BundleResource Include="Resources\Test.bundle\five.png" />
<BundleResource Include="Resources\Test.bundle\six.png" />
<BundleResource Include="Resources\Test.bundle\seven.png" />
</ItemGroup>
First, sed isn't really your best option here, but since you asked for sed...
Here's a crude first pass.
$: cat new
<ItemGroup>
<BundleResource Include="Resources\some_other_file.json" />
<BundleResource Include="Resources\Test.bundle\four.png" />
<BundleResource Include="Resources\Test.bundle\five.png" />
<BundleResource Include="Resources\Test.bundle\six.png" />
<BundleResource Include="Resources\Test.bundle\seven.png" />
</ItemGroup>
$: cat old
stuff before
...
more stuff
<ItemGroup>
<BundleResource Include="Resources\some_other_file.json" />
<BundleResource Include="Resources\Test.bundle\one.png" />
<BundleResource Include="Resources\Test.bundle\two.png" />
<BundleResource Include="Resources\Test.bundle\three.png" />
</ItemGroup>
stuff after
...
more stuff.
$: sed -n '/<ItemGroup>/,/<[/]ItemGroup>/{ /<ItemGroup>/h;
/<[/]ItemGroup>/{ H; s/^.*//; x; /Test[.]bundle/{ s/^.*/cat new/e; }; p; d; }
H; d; }; p; ' old
stuff before
...
more stuff
<ItemGroup>
<BundleResource Include="Resources\some_other_file.json" />
<BundleResource Include="Resources\Test.bundle\four.png" />
<BundleResource Include="Resources\Test.bundle\five.png" />
<BundleResource Include="Resources\Test.bundle\six.png" />
<BundleResource Include="Resources\Test.bundle\seven.png" />
</ItemGroup>
stuff after
...
more stuff.
This obviously makes some simple assumptions about your file structure.
The same logic in awk:
awk 'NR == FNR { new=new$0"\n"; next; }
/<ItemGroup>/,/<[/]ItemGroup>/{ grp=grp$0"\n";
if ($0 ~ "</ItemGroup>") { if (grp ~ "Test.bundle") { print new } else { print grp } grp="" } else next;
} 1' new old
In vtp ( or xml? ) files I have a set of points with position (x,y,z), mass (m) and densities (rho) for each points.
They look like so
<?xml version="1.0"?>
<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<PolyData>
<Piece NumberOfPoints="524288" NumberOfVerts="0" NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="0" >
<PointData>
<DataArray type="Float32" Name="vx" format="appended" RangeMin="-10617.716797" RangeMax="11650.322266" offset="0" />
<DataArray type="Float32" Name="vy" format="appended" RangeMin="-12008.198242" RangeMax="11676.560547" offset="2554076" />
<DataArray type="Float32" Name="vz" format="appended" RangeMin="-10880.447266" RangeMax="11361.508789" offset="5104080" />
<DataArray type="Float32" Name="mass" format="appended" RangeMin="0.16916139424" RangeMax="0.83083856106" offset="7655432" />
<DataArray type="Float32" Name="uu" format="appended" RangeMin="0" RangeMax="117252.91406" offset="7742064" />
<DataArray type="Float32" Name="hh" format="appended" RangeMin="0" RangeMax="4.1185030937" offset="8877700" />
<DataArray type="Float32" Name="mu" format="appended" RangeMin="1.2307692766" RangeMax="1.2307692766" offset="10032668" />
<DataArray type="Float32" Name="rho" format="appended" RangeMin="0" RangeMax="49503150080" offset="10038236" />
<DataArray type="Float32" Name="phi" format="appended" RangeMin="-1.3579902649" RangeMax="1.2645899057" offset="11265024" />
<DataArray type="Int64" Name="id" format="appended" RangeMin="0" RangeMax="524287" offset="13840232" />
<DataArray type="UInt16" Name="mask" format="appended" RangeMin="0" RangeMax="3" offset="15044924" />
</PointData>
<CellData>
</CellData>
<Points>
<DataArray type="Float32" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0.89113022864" RangeMax="110.020575" offset="15133592" />
</Points>
<Verts>
<DataArray type="Int64" Name="connectivity" format="appended" RangeMin="" RangeMax="" offset="22080132" />
<DataArray type="Int64" Name="offsets" format="appended" RangeMin="" RangeMax="" offset="22080148" />
</Verts>
<Lines>
<DataArray type="Int64" Name="connectivity" format="appended" RangeMin="" RangeMax="" offset="22080164" />
<DataArray type="Int64" Name="offsets" format="appended" RangeMin="" RangeMax="" offset="22080180" />
</Lines>
<Strips>
<DataArray type="Int64" Name="connectivity" format="appended" RangeMin="" RangeMax="" offset="22080196" />
<DataArray type="Int64" Name="offsets" format="appended" RangeMin="" RangeMax="" offset="22080212" />
</Strips>
<Polys>
<DataArray type="Int64" Name="connectivity" format="appended" RangeMin="" RangeMax="" offset="22080228" />
<DataArray type="Int64" Name="offsets" format="appended" RangeMin="" RangeMax="" offset="22080244" />
</Polys>
</Piece>
</PolyData>
<AppendedData encoding="base64">
...
</AppendedData>
</VTKFile
I would like to use this to do some volume rendering, therefore I need to have it as ImageData.
My first stupid approach is this : using a vtkXMLImageDataReader instead of a vtkXMLPolyDataReader. It obviously didn't work.
What can I do to convert it to ImageData or make it work with any volumeMapper?
Thanks
With vtkplotter you can create a vtkVolume interpolating from a sparse set of points:
from vtkplotter import *
mymesh = ... # vtkPolyData with pointdata
vol = interpolateToVolume(Actor(mymesh))
#write(vol, 'output.vti')
show(vol)
see here.
I might be missing something in the question. But from my understanding, you can simpy follow this example: link
This is how my Save As works - it is copying the current file's lines until it reaches the first figure and then I use my print methods to print the figure's info and then close the tag.
std::ofstream newFile(filePath1_fixed, std::ios::app);
std::fstream openedFile(filePath);
std::string line1;
while (std::getline(openedFile, line1)) {
if (line1.find("<rect") != std::string::npos
|| line1.find("<circle") != std::string::npos
|| line1.find("<line") != std::string::npos)
break;
newFile << line1 << std::endl;
}
figc.printToFile(newFile);
newFile << "</svg>\n";
My question is how to save the changes to the current file? I tried something like this:
std::ifstream openedFile(filePath);
std::ofstream newFile(filePath, std::ios::app);
std::string line1;
std::string info_beg[100];
int t = 0;
while (std::getline(openedFile, line1)) {
std::cout << "HELLYEAH";
if (line1.find("<rect") != std::string::npos
|| line1.find("<circle") != std::string::npos
|| line1.find("<line") != std::string::npos)
break;
info_beg[t++] = line1;
}
for (int i = 0; i < t; i++)
newFile << info_beg[i] << std::endl;
figc.printToFile(newFile);
newFile << "</svg>\n";
This is the nearest I've gone. I get this:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<desc>Example rect01 - rectangle with sharp corners</desc>
<!-- Show outline of canvas using 'rect' element -->
<rect x="1" y="1" width="1198" height="398"
fill="none" stroke="blue" stroke-width="2" />
<line x1="20" y1="100" x2="100" y2="20"
stroke="red" stroke-width="2" />
<rect x="20" y="30" width="40" height="50"
fill="red" stroke="red" stroke-width="1" />
<rect x="10" y="20" width="30" height="40"
fill="red" stroke="blue" stroke-width="1" />
<line x1="100" y1="200" x2="300" y2="400"
stroke="red" stroke-width="2" />
<circle cx="10" cy="20" r="30"
fill="red" stroke="blue" stroke-width="2" />
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<desc>Example rect01 - rectangle with sharp corners</desc>
<!-- Show outline of canvas using 'rect' element -->
<rect x="1" y="1" width="1198" height="398"
fill="none" stroke="blue" stroke-width="2" />
<line x1="20" y1="100" x2="100" y2="20"
stroke="red" stroke-width="2" />
<rect x="20" y="30" width="40" height="50"
fill="red" stroke="red" stroke-width="1" />
<rect x="10" y="20" width="30" height="40"
fill="red" stroke="blue" stroke-width="1" />
<line x1="100" y1="200" x2="300" y2="400"
stroke="red" stroke-width="2" />
<circle cx="10" cy="20" r="30"
fill="red" stroke="blue" stroke-width="2" />
<rect x="10" y="20" width="30" height="40"
fill="red" stroke="blue" stroke-width="2" />
</svg>
So my actual question is how to delete the first or overwrite it or I need a different approach.
Use ios::trunc instead of ios::app
Using std::ios::app in the constructor for your std::ofstream tells the program to append to the file and not overwrite it. If you want to overwrite it (ie truncate), then using std::ios::trunc will tell the program to overwrite the existing file. ofstream does this by default, so you could just write the initialization as just std::ofstream newFile(filePath);.
Also, don't try to read the file and write to it at the same time; that won't work. Use ifstream to get the data into the buffer, then use close() to close the file. Then initialize newFile to overwrite the file and write out the buffer.
Updating this post with new information. I am enclosing the entire XSLT as it is fairly complicated and I am not entirely sure what to withhold to maintain the integrity and cause of the issue. Also, I am going to include the input which I have minimized as much as I could to also maintain integrity of the data. What I am not including is the xsd of the EDI X12 856. this is proprietary and it is also very large. If you are using Biztalk EDI, you already have the schema necessary. If there is information I can provide from this schema that will help answer this question please let me know and I will post anything you need. And if there is somewhere I can put the .xsd like a repository or email, let me know.
The problem is I am trying to reach out to the LIN/LIN11 element and put the contents in the DTM02 element for each iteration. I am either missing syntax to do this or I may need some global variable to spin through the instances. But really new to XSLT and its processing. Could really use some direction and a solution would be great.
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var"
exclude-result-prefixes="msxsl var ScriptNS0 userCSharp"
version="1.0"
xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006"
xmlns:ScriptNS0="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0"
xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates select="/ns0:X12_00401_856" />
</xsl:template>
<xsl:template match="/ns0:X12_00401_856">
<xsl:variable name="var:BSN05" select="userCSharp:StringConcat("0001")" />
<xsl:if test="userCSharp:InistrLastPackID()" />
<xsl:variable name="var:OrderNo" select="ns0:HLLoop1[ns0:HL/HL03='O']/ns0:PRF/PRF01" />
<xsl:variable name="var:PurchaseOrderNo" select="ns0:HLLoop1[ns0:HL/HL03='O']/ns0:PRF/PRF06" />
<ns0:X12_00401_856>
<ns0:BSN>
<BSN01>
<xsl:text>00</xsl:text>
</BSN01>
<BSN02>
<xsl:value-of select="ns0:BSN/BSN02/text()" />
</BSN02>
<xsl:variable name="var:v1" select="ScriptNS0:GetEDIDate(string(ns0:BSN/BSN03/text()))" />
<xsl:variable name="var:v2" select="userCSharp:LogicalNe(string($var:v1) , "")" />
<xsl:if test="string($var:v2)='true'">
<xsl:variable name="var:v3" select="ns0:BSN/BSN03/text()" />
<BSN03>
<xsl:value-of select="$var:v3" />
</BSN03>
</xsl:if>
<BSN04>
<xsl:value-of select="ns0:BSN/BSN04/text()" />
</BSN04>
<BSN05>
<xsl:value-of select="$var:BSN05" />
</BSN05>
</ns0:BSN>
<!--Inital the strLastPackID in the begining of the template-->
<!--Shipment-->
<xsl:element name="ns0:HLLoop1">
<xsl:variable name="var:ShipmentHLLoop1" select="ns0:HLLoop1[ns0:HL/HL03='S']" />
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('S')" />
</xsl:element>
<xsl:element name="HL03">S</xsl:element>
</xsl:element>
<xsl:variable name="var:v35" select="userCSharp:StringConcat('BM')" />
<xsl:variable name="var:v36" select="userCSharp:StringConcat('5774125')" />
<xsl:variable name="var:v37" select="userCSharp:StringConcat('SN')" />
<xsl:variable name="var:v38" select="userCSharp:StringConcat('IA')" />
<xsl:variable name="var:v40" select="$var:v35" />
<xsl:variable name="var:v41" select="$var:v36" />
<xsl:variable name="var:v42" select="$var:v37" />
<xsl:variable name="var:v43" select="ns0:TD3/TD303/text()" />
<xsl:variable name="var:v44" select="$var:v38" />
<xsl:variable name="var:v46" select="ScriptNS0:GetRollaShipmentByOrderNo(string($var:OrderNo/text()))" />
<xsl:variable name="var:v47" select="ScriptNS0:PullElementAfterQualifier('VehID', string($var:v46))" />
<!--Ship To-->
<xsl:element name="ns0:N1Loop1">
<xsl:variable name="var:STN1Loop1" select="$var:ShipmentHLLoop1/ns0:N1Loop1[ns0:N1/N101='ST']" />
<xsl:element name="ns0:N1">
<xsl:element name="N101">ST</xsl:element>
<xsl:element name="N102">
<xsl:value-of select="$var:STN1Loop1/ns0:N1/N102" />
</xsl:element>
<xsl:element name="N103">92</xsl:element>
<xsl:element name="N104">
<xsl:value-of select="$var:STN1Loop1/ns0:N1/N104" />
</xsl:element>
</xsl:element>
<!--End of N1-->
</xsl:element>
<!--End of N1Loop1-->
</xsl:element>
<!--End of HLLoop1-->
<!--Order-->
<xsl:element name="ns0:HLLoop1">
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('O')" />
</xsl:element>
<xsl:element name="HL02">
<xsl:value-of select="userCSharp:ReturnHL02('S')" />
</xsl:element>
<xsl:element name="HL03">O</xsl:element>
</xsl:element>
<!--End HL-->
<xsl:element name="ns0:PRF">
<xsl:element name="PRF01">
<xsl:value-of select="$var:PurchaseOrderNo" />
</xsl:element>
</xsl:element>
<!--End PRF-->
</xsl:element>
<!--End HLLoop1-->
<xsl:for-each select="ns0:HLLoop1">
<!--don't include S or O levels-->
<xsl:if test="ns0:HL/HL03 = 'T' or ns0:HL/HL03 = 'I'">
<!--Pack-->
<xsl:if test="ns0:HL/HL03 = 'T'">
<xsl:element name="ns0:HLLoop1">
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('T')" />
</xsl:element>
<xsl:element name="HL02">
<xsl:value-of select="userCSharp:ReturnHL02('O')" />
</xsl:element>
<xsl:element name="HL03">T</xsl:element>
</xsl:element>
<xsl:element name="ns0:MAN">
<xsl:element name="MAN01">GM</xsl:element>
<xsl:element name="MAN02">
<xsl:value-of select="ns0:MAN/MAN02" />
</xsl:element>
</xsl:element>
<!--End of MAN-->
<xsl:element name="ns0:DTM_2">
<xsl:element name="DTM01">036</xsl:element>
<xsl:element name="DTM02">
<xsl:value-of select="ns0:LIN/LIN11" />
</xsl:element>
</xsl:element>
</xsl:element>
<!--End of HLLoop1 Pack-->
</xsl:if>
<!--Item-->
<xsl:if test="ns0:HL/HL03 = 'I'">
<!--Item-->
<xsl:element name="ns0:HLLoop1">
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('I')" />
</xsl:element>
<xsl:element name="HL02">
<xsl:value-of select="userCSharp:ReturnHL02('T')" />
</xsl:element>
<xsl:element name="HL03">I</xsl:element>
</xsl:element>
<xsl:element name="ns0:LIN">
<xsl:element name="LIN01">
<xsl:value-of select="ns0:LIN/LIN01 div 10000" />
</xsl:element>
<xsl:element name="LIN02">UP</xsl:element>
<xsl:element name="LIN03">
<xsl:value-of select="ns0:LIN/LIN03" />
</xsl:element>
</xsl:element>
<!--End of LIN-->
<xsl:element name="SN1">
<xsl:element name="SN102">
<xsl:value-of select="ns0:SN1/SN102" />
</xsl:element>
<xsl:element name="SN103">EA</xsl:element>
</xsl:element>
<!--End of SN1-->
</xsl:element>
<!--End of HLLoop1 Item-->
</xsl:if>
</xsl:if>
</xsl:for-each>
<!--End of Pack/Item For Each-->
</ns0:X12_00401_856>
</xsl:template>
<msxsl:script language="C#" implements-prefix="userCSharp">
<![CDATA[
int HL01 = 0;
int ShipHL = 0;
int OrdrHL = 0;
int PackHL = 0;
int ItemHL = 0;
//This function increments the hl01 value then stores the value into the
//appropriate "last" object variable. It returns the value of hl01 to the
//XSLT script.
public string ReturnHL01(string LevelCode)
{
HL01 += 1;
if (LevelCode == "S")
ShipHL = HL01;
if (LevelCode == "O")
OrdrHL = HL01;
if (LevelCode == "P")
PackHL = HL01;
if (LevelCode == "I")
ItemHL = HL01;
return HL01.ToString();
}
public string ReplaceMe(string str_Input)
{
return str_Input.Replace("-","");
}
public string ReturnQTY(string str_Qty, string str_QtyPerUOM)
{
string[] strarrayQty = str_Qty.Split('.');
string[] strarrayQtyPerUOM = str_QtyPerUOM.Split('.');
str_Qty = strarrayQty[0];
str_QtyPerUOM = strarrayQtyPerUOM[0];
int int_Qty = Convert.ToInt32(str_Qty);
int int_QtyPerUOM = Convert.ToInt32(str_QtyPerUOM);
return (int_Qty * int_QtyPerUOM).ToString();
}
//This function returns the HL02
public string ReturnHL02(string LevelCode)
{
int retlevel = 0;
if (LevelCode == "S")
retlevel = ShipHL;
if (LevelCode == "O")
retlevel = OrdrHL;
if (LevelCode == "P")
retlevel = PackHL;
if (LevelCode == "I")
retlevel = ItemHL;
return retlevel.ToString();
}
/*This Function used to check if the current pack is the same with previous pack,
if the pack is the same, then return string "1", if it is difference, then return "0" */
string strLastPackID;
public void InistrLastPackID()
{
strLastPackID = "";
}
public string CheckIfTheSamePack(string strCurrentPackID)
{
if (strLastPackID == strCurrentPackID)
{
return "1";
}
else
{
strLastPackID = strCurrentPackID;
return "0";
}
}
public string GetReleaseFromPORelease(string str_PO)
{
if (str_PO.Contains("_"))
{
string[] strarray_PO = str_PO.Split('_');
return strarray_PO[1];
}
else
{
return str_PO;
}
}
public string GetMars856STCode(string str_CustomerNumber, string str_STState)
{
string duns;
if (str_CustomerNumber.Contains("NUTRO"))
{
switch (str_STState)
{
case "CA":
duns = "007134919000Y";
break;
case "TN":
duns = "007134919000U";
break;
default:
duns = "BADDUNS";
break;
}
return duns;
}
else
{
switch (str_STState)
{
case "CA":
duns = "0071349190097";
break;
case "GA":
duns = "0071349190031";
break;
case "TX":
duns = "0071349190079";
break;
case "SC":
duns = "0071349190096";
break;
case "OH":
duns = "0071349190041";
break;
default:
duns = "BADDUNS";
break;
}
return duns;
}
}
public string MathDivide(string val1, string val2)
{
string retval = "";
double d1 = 0;
double d2 = 0;
if (IsNumeric1(val1, ref d1) && IsNumeric1(val2, ref d2))
{
if (d2 != 0)
{
double ret = d1 / d2;
retval = ret.ToString();
}
}
return retval;
}
public bool IsNumeric1(string val)
{
if (val == null)
{
return false;
}
double d = 0;
return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d);
}
public bool IsNumeric1(string val, ref double d)
{
if (val == null)
{
return false;
}
return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d);
}
public string StringConcat(string param0)
{
return param0;
}
public bool LogicalNe(string val1, string val2)
{
bool ret = false;
double d1 = 0;
double d2 = 0;
if (IsNumeric(val1, ref d1) && IsNumeric(val2, ref d2))
{
ret = d1 != d2;
}
else
{
ret = String.Compare(val1, val2, StringComparison.Ordinal) != 0;
}
return ret;
}
public bool IsNumeric(string val)
{
if (val == null)
{
return false;
}
double d = 0;
return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d);
}
public bool IsNumeric(string val, ref double d)
{
if (val == null)
{
return false;
}
return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d);
}
public string GetExpirationDate(string str_Mfg_Date, string str_Shelf_Life)
{
DateTime dt = System.Convert.ToDateTime(str_Mfg_Date);
dt = dt.AddDays(System.Convert.ToInt32(str_Shelf_Life));
return dt.ToString("yyyyMMdd");
}
]]></msxsl:script>
</xsl:stylesheet>
input data:
<?xml version="1.0" encoding="utf-8"?>
<ns0:X12_00401_856 xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<ST>
<ST01>856</ST01>
<ST02>0001</ST02>
</ST>
<ns0:BSN>
<BSN01>00</BSN01>
<BSN02>SID0000378</BSN02>
<BSN03>20160824</BSN03>
<BSN04>172952</BSN04>
<BSN05>0001</BSN05>
</ns0:BSN>
<ns0:HLLoop1>
<ns0:HL>
<HL01>1</HL01>
<HL03>S</HL03>
</ns0:HL>
<ns0:TD1>
<TD101>PLT94</TD101>
<TD102>4</TD102>
<TD106>G</TD106>
<TD107>52448.00</TD107>
<TD108>LB</TD108>
</ns0:TD1>
<ns0:TD5>
<TD502>2</TD502>
<TD503>ANSH</TD503>
<TD504>M</TD504>
</ns0:TD5>
<ns0:TD3>
<TD301>TL</TD301>
<TD309>TRL0000590</TD309>
</ns0:TD3>
<ns0:REF>
<REF01>SN</REF01>
<REF02>SEAL082401</REF02>
</ns0:REF>
<ns0:REF>
<REF01>BM</REF01>
<REF02>10401217</REF02>
</ns0:REF>
<ns0:DTM_2>
<DTM01>011</DTM01>
<DTM02>20160819</DTM02>
</ns0:DTM_2>
<ns0:N1Loop1>
<ns0:N1>
<N101>SF</N101>
<N102>any name</N102>
<N103>92</N103>
<N104>61</N104>
</ns0:N1>
<ns0:N3>
<N301>101 Your WAY</N301>
</ns0:N3>
<ns0:N4>
<N401>Irvine</N401>
<N402>CA</N402>
<N403>91111</N403>
<N404>USA</N404>
</ns0:N4>
</ns0:N1Loop1>
<ns0:N1Loop1>
<ns0:N1>
<N101>ST</N101>
<N102>0010</N102>
<N103>92</N103>
<N104>0010</N104>
</ns0:N1>
<ns0:N3>
<N301>1234 My Way Ct</N301>
</ns0:N3>
<ns0:N4>
<N401>GROVEPORT</N401>
<N402>OH</N402>
<N403>43125</N403>
<N404>USA</N404>
</ns0:N4>
</ns0:N1Loop1>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>2</HL01>
<HL03>O</HL03>
</ns0:HL>
<ns0:PRF>
<PRF01>10401217</PRF01>
<PRF04>20160822</PRF04>
<PRF06>10401217</PRF06>
<PRF07>KN</PRF07>
</ns0:PRF>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>3</HL01>
<HL03>T</HL03>
</ns0:HL>
<ns0:MAN>
<MAN01>GM</MAN01>
<MAN02>L000000000T5</MAN02>
</ns0:MAN>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>4</HL01>
<HL03>I</HL03>
</ns0:HL>
<ns0:LIN>
<LIN01>20000</LIN01>
<LIN02>UP</LIN02>
<LIN03>030111169051</LIN03>
<LIN04>VN</LIN04>
<LIN05>416905</LIN05>
<LIN10>RU</LIN10>
<LIN11>20180614</LIN11>
</ns0:LIN>
<ns0:SN1>
<SN102>32</SN102>
<SN103>EA</SN103>
</ns0:SN1>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>5</HL01>
<HL03>T</HL03>
</ns0:HL>
<ns0:MAN>
<MAN01>GM</MAN01>
<MAN02>L000000000T6</MAN02>
</ns0:MAN>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>6</HL01>
<HL03>I</HL03>
</ns0:HL>
<ns0:LIN>
<LIN01>20000</LIN01>
<LIN02>UP</LIN02>
<LIN03>030111169051</LIN03>
<LIN04>VN</LIN04>
<LIN05>416905</LIN05>
<LIN10>RU</LIN10>
<LIN11>20180614</LIN11>
</ns0:LIN>
<ns0:SN1>
<SN102>32</SN102>
<SN103>EA</SN103>
</ns0:SN1>
</ns0:HLLoop1>
<ns0:CTT>
<CTT01>6</CTT01>
</ns0:CTT>
<SE>
<SE01>79</SE01>
<SE02>0001</SE02>
</SE>
</ns0:X12_00401_856>
Your XSLT is only outputting the DTM node(s) when HL03 = 'T', but your input doc only has LIN/LIN11 where HL03 is something else (I).
If you want to avoid outputting a DTM node when there is no LIN11, then you could do it like so:
<!--Pack-->
<xsl:if test="ns0:HL/HL03 = 'T'">
<xsl:element name="ns0:HLLoop1">
<xsl:element name="ns0:HL">
<xsl:element name="HL01">
<xsl:value-of select="userCSharp:ReturnHL01('T')" />
</xsl:element>
<xsl:element name="HL02">
<xsl:value-of select="userCSharp:ReturnHL02('O')" />
</xsl:element>
<xsl:element name="HL03">T</xsl:element>
</xsl:element>
<xsl:element name="ns0:MAN">
<xsl:element name="MAN01">GM</xsl:element>
<xsl:element name="MAN02">
<xsl:value-of select="ns0:MAN/MAN02" />
</xsl:element>
</xsl:element>
<!--End of MAN-->
<xsl:if test="ns0:LIN/LIN11">
<xsl:element name="ns0:DTM_2">
<xsl:element name="DTM01">036</xsl:element>
<xsl:element name="DTM02">
<xsl:value-of select="ns0:LIN/LIN11"/>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:element>
<!--End of HLLoop1 Pack-->
</xsl:if>
If you need the following LIN11 node, you could use code like this:
<xsl:element name="DTM02">
<xsl:value-of select="following::LIN11[1]"/>
</xsl:element>
But this seems suspicious and prone to getting broken (what if there is no following LIN11, what if it's 10 HL loops down and gets reused multiple times, etc...). You may be best off getting the following HL loop that has HL03 = 'I', perhaps using something like here XSLT: Loop selecting two elements at a time
I have the following XSLT and using Stylus. No matter what I do I get the following error message for Line number 50.
Cannot find a matching 1-argument function named {http://schemas.microsoft.com/BizTalk/2003/userCSharp}ReplaceYYYMMDDtoXsdDate()
encoding="UTF-8" at the does not help.
Adding msxsl:assembly and msxsl:using do not help
Appreciate hints and help.
Regards, Toraj
<?xml version='1.0' ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp ScriptNS0" version="1.0" xmlns:ns0="http://schemas.microsoft.com/dynamics/2008/01/documents/AdecPOItemArrival"
xmlns:st="http://schemas.microsoft.com/dynamics/2008/01/sharedtypes" xmlns:s0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp" xmlns:ScriptNS0="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0">
<xsl:output indent="yes" omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<xsl:apply-templates select="s0:X12_00401_856" />
</xsl:template>
<!-- Use the following inside BizTalk Scripting Fuctoid - Start -->
<xsl:template name="CopyOrderTemplate" match="s0:X12_00401_856" xmlns:s0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<xsl:copy>
<xsl:apply-templates select="s0:HLLoop1[.//HL03/text()='O']" />
</xsl:copy>
</xsl:template>
<xsl:template name="WMSJournalTableTemplate" match="s0:HLLoop1[.//HL03/text()='O']">
<ns0:WMSJournalTable class="entity" Number="{.//PRF01}">
<xsl:apply-templates select="following-sibling::s0:HLLoop1[.//HL03/text()='I'][generate-id(preceding-sibling::s0:HLLoop1[.//HL03/text()='O'][1])=generate-id(current())]" />
</ns0:WMSJournalTable>
</xsl:template>
<xsl:template name="WMSJournalTransTemplate" match="s0:HLLoop1[.//HL03/text()='I']">
<ns0:WMSJournalTrans class="entity" Number="{.//LIN01}">
<xsl:variable name="Qty" select="s0:SN1/SN102/text()" />
<ns0:Qty>
<xsl:value-of select="$Qty" />
</ns0:Qty>
<xsl:variable name="TestData" select="../s0:DTM/DTM02/text()" />
<ns0:TestDataTst>
<xsl:value-of select="$TestData" />
</ns0:TestDataTst>
<!-- From BizTalk Validate XSLT
<xsl:variable name="var:v29" select="userCSharp:ReplaceYYYMMDDtoXsdDate(string(../../../s0:DTM/DTM02/text()))" /> -->
<!-- <xsl:variable name="var:v29" select="userCSharp:ReplaceYYYMMDDtoXsdDate(string(../s0:DTM/DTM02/text()))"/> -->
<xsl:variable name="var:v29" select="userCSharp:ReplaceYYYMMDDtoXsdDate($TestData)" />
<ns0:TransDate>
<xsl:value-of select="$var:v29" />
</ns0:TransDate>
<xsl:variable name="VendAccount" select="'13458'" />
<ns0:VendAccount>
<xsl:value-of select="$VendAccount" />
</ns0:VendAccount>
</ns0:WMSJournalTrans>
</xsl:template>
<msxsl:script language="C#" implements-prefix="userCSharp">
<!-- <msxsl:script implements-prefix='userCSharp' language='C#'>
<msxsl:assembly href="C:\Users\toraj.khavari\Documents\StylusProjects\856\Adec.Common.Modification.dll"/>
<msxsl:using namespace="Adec.Common.Modification" />
<msxsl:using namespace="System" />-->
<![CDATA[
/// <summary>
/// Replaces the yyyymmddd date to XSD date.
/// </summary>
/// <param name="stringInput">The string input.</param>
/// <returns></returns>
public string ReplaceYYYMMDDtoXsdDate(string stringInput)
{
System.String resultStr = "NotFound";
string year = null;
string month = null;
string day = null;
try
{
if (!System.String.IsNullOrEmpty(stringInput) && (stringInput.Length > 7))
{
// IsDigitsOnly
foreach (char c in stringInput)
{
if (c < '0' || c > '9')
return resultStr = "Invalid Input string values";
}
year = stringInput.Substring(0, 4);
month = stringInput.Substring(4, 2);
day = stringInput.Substring(6, 2);
resultStr = String.Format("{0}-{1}-{2}", year, month, day);
}
else
{
resultStr = "Invalid Input string values";
}
}
catch
{
resultStr = "ExceptionError in ReplaceYYYMMDDtoXsdDateTime";
}
return resultStr;
}
]]>
</msxsl:script>
<!-- Use the bove inside BizTalk Scripting Fuctoid - END -->
</xsl:stylesheet>
Code attached
Well msxsl:script is a proprietary Microsoft feature implemented in some XSLT 1.0 processor by Microsoft like the various MSXML version (which however don't support calling into .NET languages like C#, you can only call VBScript or JScript extension functions) or like XslCompiledTransform. I don't know which XSLT processors you can use with Stylus Studio but I think by default it uses Saxon and that does not support the Microsoft specific extension to call into C#. So you will need to check whether Stylus Studio allows you to switch to Microsoft's XslCompiledTransform as the XSLT processor.