明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 681|回复: 0

Transforming a list of RegAppIds from XML to HTML using XSLT

[复制链接]
发表于 2011-2-24 22:59:50 | 显示全部楼层 |阅读模式
As raised as a possibility at the end of the last post, I did choose to throw together a quick
XSLT stylesheet to generate an HTML report of the XML data created by our XRA command.
To enable this I did make a few changes to our command implementation, which we’ll take a look at first.
Here’s the updated C# code, with new/modified lines in red (and here’s the updated source file):
    1 using Autodesk.AutoCAD.ApplicationServices;
    2 using Autodesk.AutoCAD.DatabaseServices;
    3 using Autodesk.AutoCAD.EditorInput;
    4 using Autodesk.AutoCAD.Runtime;
    5 using System.Collections.Generic;
    6 using System.Text;
    7 using System.Xml;
    8 using System.Xml.Serialization;
    9 using System.IO;
   10 using System;
   11
   12 namespace XrefRegApps
   13 {
   14   [XmlRoot("RegAppData")]
   15
public
class
RegAppData
   16   {
   17
// The name of our drawing
   18
   19
private
string _name;
   20
   21     [XmlAttribute("Name")]
   22
public
string Name
   23     {
   24
get { return _name; }
   25
set { _name = value; }
   26     }
   27
   28
// The location of our drawing
   29
   30
private
string _dwg;
   31
   32     [XmlAttribute("File")]
   33
public
string File
   34     {
   35
get { return _dwg; }
   36
set { _dwg = value; }
   37     }
   38
   39
private
string _dwgVersion;
   40
   41     [XmlAttribute("DwgVersion")]
   42
public
string DwgVersion
   43     {
   44
get { return _dwgVersion; }
   45
set { _dwgVersion = value; }
   46     }
   47
   48
// The list of our drawing's Registered Application IDs
   49
   50
private
List<string> _regAppIds = new
List<string>();
   51
   52     [XmlArrayItem("RegAppId")]
   53
public
List<string> RegAppIds
   54     {
   55
get { return _regAppIds; }
   56
set { _regAppIds = value; }
   57     }
   58
   59
public
void AddRegAppId(string id)
   60     {
   61
if (!_regAppIds.Contains(id))
   62         _regAppIds.Add(id);
   63     }
   64   }
   65
   66
public
class
Commands
   67   {
   68
private
const
string regAppDataXml = "c:\\RegAppData.xml";
   69
   70
private
void SerializeRegAppData(
   71
Dictionary<string, RegAppData> dict
   72     )
   73     {
   74
if (dict.Count > 0)
   75       {
   76
// No direct way to serialize a dictionary to XML,
   77
// so we'll create a list from it and serialize that
   78
   79
List<RegAppData> regData =
   80
new
List<RegAppData>(dict.Count);
   81
foreach (KeyValuePair<string, RegAppData> kv in dict)
   82         {
   83           regData.Add(kv.Value);
   84         }
   85
   86
// Serialize our list to the specified XML file
   87
   88
XmlSerializer xs =
   89
new
XmlSerializer(typeof(List<RegAppData>));
   90
XmlTextWriter xw =
   91
new
XmlTextWriter(regAppDataXml, Encoding.UTF8);
   92         xw.WriteProcessingInstruction(
   93
"xml-stylesheet",
   94
"type=\"text/xsl\" href=\"RegAppData.xslt\""
   95         );
   96         xs.Serialize(xw, regData);
   97         xw.Close();
   98       }
   99     }
  100
  101
// Read and return the previous Registered Application data
  102
// from our stored XML file
  103
  104
private
Dictionary<string, RegAppData>
  105       DeserializeRegAppData()
  106     {
  107
if (File.Exists(regAppDataXml))
  108       {
  109
XmlSerializer xs =
  110
new
XmlSerializer(typeof(List<RegAppData>));
  111
XmlTextReader xr = new
XmlTextReader(regAppDataXml);
  112
if (xs.CanDeserialize(xr))
  113         {
  114
// No direct way to serialize a dictionary to XML,
  115
// so we'll read a list and populate a dictionary
  116
// from it
  117
  118
List<RegAppData> regData =
  119             (List<RegAppData>)xs.Deserialize(xr);
  120           xr.Close();
  121
Dictionary<string, RegAppData> dict =
  122
new
Dictionary<string, RegAppData>();
  123
foreach (RegAppData rad in regData)
  124           {
  125             dict.Add(rad.File, rad);
  126           }
  127
return dict;
  128         }
  129       }
  130
return
new
Dictionary<string, RegAppData>();
  131     }
  132
  133     [CommandMethod("XRA")]
  134
public
void ExternalReferenceRegisteredApps()
  135     {
  136
Document doc =
  137
Application.DocumentManager.MdiActiveDocument;
  138
Database db = doc.Database;
  139
Editor ed = doc.Editor;
  140
  141
// Prompt the user for the path to a DWG to test
  142
  143
PromptStringOptions pso =
  144
new
PromptStringOptions(
  145
"\nEnter path to root drawing file: "
  146         );
  147       pso.AllowSpaces = true;
  148
PromptResult pr = ed.GetString(pso);
  149
if (pr.Status != PromptStatus.OK)
  150
return;
  151
  152
if (!File.Exists(pr.StringResult))
  153       {
  154         ed.WriteMessage("\nFile does not exist.");
  155
return;
  156       }
  157
  158
try
  159       {
  160
// We start by reading any existing RegApp data
  161
// from XML
  162
  163
Dictionary<string, RegAppData> regData =
  164           DeserializeRegAppData();
  165
  166
// Load the DWG into a side database
  167
  168
Database mainDb = new
Database(false, true);
  169
using (mainDb)
  170         {
  171           mainDb.ReadDwgFile(
  172             pr.StringResult,
  173
FileOpenMode.OpenForReadAndAllShare,
  174
true,
  175
null
  176           );
  177
  178
// We need an additional step to resolve Xrefs
  179
  180           mainDb.ResolveXrefs(false, false);
  181
  182
// Get the XrefGraph for the specified database
  183
  184
XrefGraph xg = mainDb.GetHostDwgXrefGraph(true);
  185
  186
// Loop through the nodes in the graph
  187
  188
for (int i = 0; i < xg.NumNodes; i++)
  189           {
  190
// Get each node and check its status
  191
  192
XrefGraphNode xgn = xg.GetXrefNode(i);
  193
  194
switch (xgn.XrefStatus)
  195             {
  196
// If Un*, print a message
  197
  198
case
XrefStatus.Unresolved:
  199                 ed.WriteMessage(
  200
"\nUnresolved xref \"{0}\"", xgn.Name
  201                 );
  202
break;
  203
case
XrefStatus.Unloaded:
  204                 ed.WriteMessage(
  205
"\nUnloaded xref \"{0}\"", xgn.Name
  206                 );
  207
break;
  208
case
XrefStatus.Unreferenced:
  209                 ed.WriteMessage(
  210
"\nUnreferenced xref \"{0}\"", xgn.Name
  211                 );
  212
break;
  213
case
XrefStatus.Resolved:
  214                 {
  215
// If Resolved, get the RegAppTable
  216
  217
Database xdb = xgn.Database;
  218
if (xdb != null)
  219                   {
  220
Transaction tr =
  221                     xdb.TransactionManager.StartTransaction();
  222
using (tr)
  223                     {
  224
RegAppTable rat =
  225                         (RegAppTable)tr.GetObject(
  226                           xdb.RegAppTableId,
  227
OpenMode.ForRead
  228                         );
  229
  230
// We'll store our RegApp data in an
  231
// object
  232
  233
RegAppData dwgData = new
RegAppData();
  234                       dwgData.Name =
  235                         (i == 0 ?
  236
Path.GetFileNameWithoutExtension(
  237                             xgn.Name
  238                           ) :
  239                           xgn.Name
  240                         );
  241                       dwgData.File = xdb.Filename;
  242                       dwgData.DwgVersion =
  243                         xdb.OriginalFileVersion.ToString();
  244
  245
// Collect the contained names of the
  246
// RegAppTableRecords (the RegAppIds)
  247
// in a list
  248
  249
foreach (ObjectId id in rat)
  250                       {
  251
RegAppTableRecord ratr =
  252                           (RegAppTableRecord)tr.GetObject(
  253                             id,
  254
OpenMode.ForRead
  255                           );
  256                         dwgData.AddRegAppId(ratr.Name);
  257                       }
  258
  259
// Store the object in our dictionary,
  260
// replacing any existing item
  261
// (keyed off the entire DWG path, not
  262
// just the name)
  263
  264
if (regData.ContainsKey(dwgData.File))
  265                         regData.Remove(dwgData.File);
  266                       regData.Add(dwgData.File, dwgData);
  267
  268
// Print the drawing information
  269
// and the RegAppId count
  270
  271                       ed.WriteMessage(
  272
"\nDrawing \"{0}\" (\"{1}\") with " +
  273
"{2} RegAppIds",
  274                         dwgData.Name,
  275                         dwgData.File,
  276                         dwgData.RegAppIds.Count
  277                       );
  278
  279
// Even if only reading, commit the
  280
// transaction (it's cheaper than
  281
// aborting)
  282
  283                       tr.Commit();
  284                     }
  285                   }
  286
break;
  287                 }
  288             }
  289           }
  290
// Save our data to XML
  291
  292           SerializeRegAppData(regData);
  293         }
  294       }
  295
catch (System.Exception ex)
  296       {
  297         ed.WriteMessage(
  298
"\nProblem reading/processing \"{0}\": {1}",
  299           pr.StringResult, ex.Message
  300         );
  301       }
  302     }
  303   }
  304 }

The changes are very minor: we’ve added a DwgVersion attribute to our XML, as well as adjusting the save type of RegAppIds from being a simple string attribute to an array of elements (which allows us to determine the number of RegAppIds per drawing more easily).
We've hardcoded the path of the XML file to C:\ (feel free to change this, of course), as well as writing a stylesheet reference directly into the XML to just let the browser take care of the transformation to HTML.
Speaking of the stylesheet, here’s the RegAppData.xslt file to be placed alongside the XML output (currently in C:\, as just mentioned):
<?xml
version="1.0"
encoding="utf-8"?>
<xsl:stylesheet

version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output
method="html"
indent="yes"
version="4.0"/>

  <xsl:template
match="ArrayOfRegAppData">
    <h2>Registered application IDs per drawing</h2>
    <table>
      <tr>
        <td><em>Drawing name</em></td>
        <td>
          <em>Number of RegAppIds</em>
        </td>
      </tr>
      <xsl:apply-templates
select="*"/>
    </table>
  </xsl:template>

  <xsl:template
match="RegAppData">
    <tr>
      <td>
        <b>
          <xsl:attribute
name="Title">
            <xsl:value-of
select="@File"/>
            <xsl:text> (</xsl:text>
            <xsl:value-of
select="@DwgVersion"/>
            <xsl:text>)</xsl:text>
          </xsl:attribute>
          <xsl:value-of
select="@Name"/>
        </b>
      </td>
      <td>
        <xsl:attribute
name="Title">
          <xsl:for-each
select="RegAppIds/RegAppId">
            <xsl:value-of
select="node()"/>
            <xsl:if
test="position() != last()">
              <xsl:text>&#x0A;</xsl:text>
            </xsl:if>
          </xsl:for-each>
        </xsl:attribute>
        <center>
          <xsl:value-of
select="count(RegAppIds/RegAppId)"/>
        </center>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

The stylesheet is also quite simple: it creates an HTML file containing a table of two columns – one with the names of our drawings (with the path and version in a tooltip) and the number of RegAppIds found in that drawing (with the specific names in a tooltip). We’ll see that in action a bit.
Running the XRA command just as we did in the last post, we should see this kind of XML output:
<?xml-stylesheet
type="text/xsl" href="RegAppData.xslt"?>
<ArrayOfRegAppData

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <RegAppData

Name="A-01"

File="C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Architectural\A-01.dwg"

DwgVersion="Current">
    <RegAppIds>
      <RegAppId>ACAD</RegAppId>
      <RegAppId>CONTENTBLOCKDESCRIPTION</RegAppId>
      <RegAppId>CONTENTBLOCKICON</RegAppId>
      <RegAppId>CONTENTTABDATA</RegAppId>
      <RegAppId>CONTENTCURRENTTAB</RegAppId>
      <RegAppId>ACAD_PSEXT</RegAppId>
      <RegAppId>PE_URL</RegAppId>
      <RegAppId>RAK</RegAppId>
      <RegAppId>AcAecLayerStandard</RegAppId>
      <RegAppId>ACAD_DSTYLE_DIMTEXT_FILL</RegAppId>
      <RegAppId>ACAD_EXEMPT_FROM_CAD_STANDARDS</RegAppId>
      <RegAppId>AcDbBlockRepETag</RegAppId>
      <RegAppId>AcDbDynamicBlockTrueName</RegAppId>
      <RegAppId>AcDbDynamicBlockGUID</RegAppId>
      <RegAppId>AcDbBlockRepBTag</RegAppId>
      <RegAppId>ACAD_DSTYLE_DIMEXT_LENGTH</RegAppId>
      <RegAppId>ACAD_DSTYLE_DIMEXT_ENABLED</RegAppId>
      <RegAppId>ACAD_DSTYLE_DIM_LINETYPE</RegAppId>
      <RegAppId>ACAD_DSTYLE_DIM_EXT1_LINETYPE</RegAppId>
      <RegAppId>ACAD_DSTYLE_DIM_EXT2_LINETYPE</RegAppId>
      <RegAppId>ACAD_MLEADERVER</RegAppId>
    </RegAppIds>
  </RegAppData>
  <RegAppData

Name="Grid Plan"

File="C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Architectural\Res\Grid Plan.dwg"

DwgVersion="AC1021">
    <RegAppIds>
      <RegAppId>ACAD</RegAppId>
      <RegAppId>CONTENTBLOCKDESCRIPTION</RegAppId>
      <RegAppId>CONTENTBLOCKICON</RegAppId>
      <RegAppId>CONTENTTABDATA</RegAppId>
      <RegAppId>CONTENTCURRENTTAB</RegAppId>
      <RegAppId>ACAD_PSEXT</RegAppId>
      <RegAppId>ACAD_DSTYLE_DIMTEXT_FILL</RegAppId>
    </RegAppIds>
  </RegAppData>
  <RegAppData

Name="Wall Base"

File="C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Architectural\Res\Wall Base.dwg"

DwgVersion="AC1021">
    <RegAppIds>
      <RegAppId>ACAD</RegAppId>
      <RegAppId>CONTENTBLOCKDESCRIPTION</RegAppId>
      <RegAppId>CONTENTBLOCKICON</RegAppId>
      <RegAppId>CONTENTTABDATA</RegAppId>
      <RegAppId>CONTENTCURRENTTAB</RegAppId>
      <RegAppId>RAK</RegAppId>
      <RegAppId>AcAecLayerStandard</RegAppId>
      <RegAppId>ACAD_PSEXT</RegAppId>
      <RegAppId>PE_URL</RegAppId>
      <RegAppId>ACAD_DSTYLE_DIMTEXT_FILL</RegAppId>
      <RegAppId>ACAD_MLEADERVER</RegAppId>
    </RegAppIds>
  </RegAppData>
  <RegAppData

Name="Master Site Plan"

File="C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\Master Site Plan.dwg"

DwgVersion="AC1021">
    <RegAppIds>
      <RegAppId>ACAD</RegAppId>
      <RegAppId>RAK</RegAppId>
      <RegAppId>DCA_FIGURE_XENT</RegAppId>
      <RegAppId>ADE</RegAppId>
      <RegAppId>ALIGNMENT_DB_APP</RegAppId>
      <RegAppId>SDI_PROFILE</RegAppId>
      <RegAppId>SDSK_POINT</RegAppId>
      <RegAppId>SVPLINE</RegAppId>
      <RegAppId>ADCADD_ZZ</RegAppId>
      <RegAppId>SDSK_PMN</RegAppId>
      <RegAppId>CIVIL_DRAFT</RegAppId>
      <RegAppId>CIVIL_LINE_TABLE</RegAppId>
      <RegAppId>CIVIL_CURVE_TABLE</RegAppId>
      <RegAppId>CIVIL_SPIRAL_TABLE</RegAppId>
      <RegAppId>SDI_XSECTIONS</RegAppId>
      <RegAppId>ACAD_PSEXT</RegAppId>
      <RegAppId>ACAD_MLEADERVER</RegAppId>
      <RegAppId>DCO15</RegAppId>
    </RegAppIds>
  </RegAppData>
  <RegAppData

Name="PB-BASE"

File="C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\PB-BASE.dwg"

DwgVersion="AC1021">
    <RegAppIds>
      <RegAppId>ACAD</RegAppId>
      <RegAppId>RAK</RegAppId>
      <RegAppId>DCA_FIGURE_XENT</RegAppId>
      <RegAppId>ALIGNMENT_DB_APP</RegAppId>
      <RegAppId>SDI_PROFILE</RegAppId>
      <RegAppId>ACAD_PSEXT</RegAppId>
      <RegAppId>ACAD_MLEADERVER</RegAppId>
    </RegAppIds>
  </RegAppData>
  <RegAppData

Name="PB-EX41"

File="C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\PB-EX41.dwg"

DwgVersion="AC1021">
    <RegAppIds>
      <RegAppId>ACAD</RegAppId>
      <RegAppId>SDSK_POINT</RegAppId>
      <RegAppId>SVPLINE</RegAppId>
      <RegAppId>ACAD_PSEXT</RegAppId>
      <RegAppId>DCO15</RegAppId>
      <RegAppId>ACAD_MLEADERVER</RegAppId>
    </RegAppIds>
  </RegAppData>
  <RegAppData

Name="PB-EX61"

File="C:\Program Files\Autodesk\AutoCAD 2011\Sample\Sheet Sets\Civil\PB-EX61.dwg"

DwgVersion="AC1021">
    <RegAppIds>
      <RegAppId>ACAD</RegAppId>
      <RegAppId>SVPLINE</RegAppId>
      <RegAppId>ACAD_PSEXT</RegAppId>
      <RegAppId>DCO15</RegAppId>
      <RegAppId>ACAD_MLEADERVER</RegAppId>
    </RegAppIds>
  </RegAppData>
</ArrayOfRegAppData>

Which, when loaded into a browser, should be displayed like this:

As we hover over the name of a drawing in which we’re interested, we see its path and drawing version:

And as we hover over the RegAppId count, we see the names of the individual IDs:

That’s it for this post. We’ll wrap this series up by making some modifications to ScriptPro 2.0 in the next post.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
"觉得好,就打赏"
还没有人打赏,支持一下

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-12-24 21:13 , Processed in 0.203970 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表