4

私はXMLおよびXSLスタイルシートにかなり慣れていないので、クライアントの1人のためにスタイルシートを作成する任務を負っています。次の形式でXMLを出力するスタイルシートをすでに作成しました。

<Trip TripType="Normal">
    <Plan BeginTime="2011-08-13T10:00:00" UserDefinedTripID="777" UserDefinedRouteID="777">
        <PlanStop ArrivalTime="2011-08-13T15:30:00" ArrivalLock="true" SiteID="1" PassThru1="test1" PassThru2="test2" PassThru3="test3" PassThru4="test4">
            <PlanNote Line1="Freeform Text" Line2="Line2" Line3="Line3" />
            <PlanCargo Duration="60" BillID="" Weight="100" Units="100.0" XUnitTypeID="10" Action="Pick" />
            <PlanNote Line1="Freeform Text" Line2="Line2" Line3="Line3" />
            <PlanCargo Duration="60" BillID="" Weight="100" Units="100.0" XUnitTypeID="12" Action="Pick" />
        </PlanStop>
    </Plan>
</Trip>

出力を取得し、Trip要素内の属性にコンテンツを挿入して次のようにする必要があります。

<Trip TripID="-1" CurrentRevisionNumber="1" IsDispatch="1" IsActive="0" 
IsComplete="0" OrganizationID="4"
TripData="&lt;Trip TripType=&quot;Normal&quot;&gt;
  &lt;Plan BeginTime=&quot;2011-08-13T10:00:00&quot; UserDefinedTripID=&quot;777&quot;
  UserDefinedRouteID=&quot;777&quot;&gt;
    &lt;PlanStop ArrivalTime=&quot;2011-08-13T10:00:00&quot; ArrivalLock=&    quot;true&quot; SiteID=&quot;1&quot; PassThru1=&quot;test1&quot; PassThru2=&    quot;test2&quot; PassThru3=&quot;test3&quot; PassThru4=&quot;test4&quot;&gt;
    &lt;PlanCargo Duration=&quot;45&quot; BillID=&quot;&quot; Weight=&    quot;100&quot; Units=&quot;100.0&quot; XUnitTypeID=&quot;9&quot; Action=&quot;Pick&quot;     /&gt;
    &lt;/PlanStop&gt; />

つまり、既存のXML出力を取得して、いくつかの文字変換を実行しながら属性に入れる必要があります。

はい、それは非常に醜いです、しかしこれは彼らがそれを望む方法です。元のXSL変換からのXML出力をコピーして、<、>、 "などを<、>、"などに変換しながら属性に配置する別のXSLを作成することを考えていました(それらが何と呼ばれるかはわかりません) )。

私は解決策を求めてインターネットを探しましたが、このようなものは見つからないようです(これはばかげた要求であるためだと思います)。必要に応じて元のXSLを提供できますが、可能であれば変更したくありません。

前もって感謝します!

4

4 に答える 4

4

私は他人の愚かさから時間、労力、およびうつ病を節約し、小さな拡張機能を使用する小さな変換でこれを実装します

以下は、.NET XslCompiledTransform XSLT プロセッサを使用した例です。

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:my="my:my" exclude-result-prefixes="msxsl my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <t stupid="{my:stringize(.)}"/>
 </xsl:template>

 <msxsl:script language="c#" implements-prefix="my">
  public string stringize(XPathNavigator doc)
  {
   return doc.InnerXml;
  }
 </msxsl:script>
</xsl:stylesheet>

XML ドキュメントに適用すると、最上位要素stupidの本体のエスケープ表現を含む属性を持つ最上位要素が生成されます。

たとえば、この XML ドキュメントに変換を適用すると、次のようになります

<t>
  <a>
    <b x="y">
      <!--  Comment here -->
      <?aPI ?>
    </b>
  </a>
</t>

必要な結果が生成されます:

<t stupid="&#xD;&#xA;  &lt;a&gt;&#xD;&#xA;    &lt;b x=&quot;y&quot;&gt;&#xD;&#xA;      &lt;!--  Comment here --&gt;&#xD;&#xA;      &lt;?aPI?&gt;&#xD;&#xA;    &lt;/b&gt;&#xD;&#xA;  &lt;/a&gt;&#xD;&#xA;" />

同じアイデアを実装する変換は、さまざまなプログラミング言語で記述できる拡張関数を使用して、ほぼすべての XSLT プロセッサ用に記述できる可能性が最も高いでしょう。

于 2012-07-24T02:27:18.523 に答える
3

XML ドキュメントをレキシカル XML として属性内に挿入するのは完全に馬鹿げているという他のコメンテーターに同意する必要があります。データの所有者は、多くの力と柔軟性を失い、何の見返りも得られません。ただし、どうしてもやむを得ない場合は、自殺してください (冗談)。このオプションが気に入らない場合は、次のようなテンプレートを使用して内部 XML をシリアル化できます...

<xsl:template match="*" mode="serialise">
  <xsl:value-of select="concat('&lt;',local-name(),' ')">
  <xsl:apply-templates select="@*" mode="serialise">
  <xsl:value-of select="' &gt;'">
  <xsl:apply-templates select="*|text()" mode="serialise">
  <xsl:value-of select="concat('&lt;/',local-name(),' &gt;')">
</xsl:template>

<xsl:template match="@*" mode="serialise">
  <xsl:value-of select="concat(local-name(),'=&quot;',.,'&quot; ')">
</xsl:template>

<xsl:template match="text()" mode="serialise">
  <xsl:value-of select=".">
</xsl:template>

レキシカル XML としてエンコードする内部構造のルート要素を取得し、@mode="serialise" で <xsl:apply-templates> を呼び出します。この呼び出しの出力を文字列変数にキャプチャします。次に、文字列変数の内容を結果ツリーの任意の属性に挿入できます。

警告

これらの単純なテンプレートは、comments()、processing-instructions()、および DocTypes を処理しません。また、XDM (DOM とは対照的に) に従って、隣接するテキスト型ノード (テキスト、CDATA、文字参照など) がマージされます。また、これは名前空間では機能しません。

于 2012-07-24T01:06:01.640 に答える
2

基本的に、XMLをシリアル化し、シリアル化の結果を文字列としてキャプチャしてから、この文字列を値として属性を書き込む必要があります。XSLT1.0またはXSLT2.0でこれを行う直接的な方法はありません。XSLT 3.0には、この要件を満たすように設計された関数fn:serialize()があり、最近のバージョンのSaxonに実装されています。(以前のバージョンのSaxonでは、saxon:serialize()拡張関数を使用してこのアイデアを導入しました。他の製品にも同様の関数が含まれている場合や、独自の関数を作成できる場合があります。)XSLT自体にシリアライザーを実装することはもちろん可能です。他の人が提案しました。それはかなり退屈です。

于 2012-07-24T02:07:14.150 に答える
2

XML をエスケープされたテキストとしてシリアライズするための XSLT スタイルシートは、http://code.google.com/p/httpfox/source/browse/trunk/chrome/content/XMLPrettyPrint.xsl ?r= 3 にあります。HTML を出力しますが、ほとんどの場合、エキスパンダーなどの不要なものを削除することで、出力 XML に簡単に適応させることができます。

唯一の注意が必要なのは、既存の XSL からの XML 出力を新しいテンプレートへの入力として取得することです。後者を別のスタイルシートとして実装する場合、または XSLT 2.0 を使用する場合、これは問題ありません。それ以外の場合は、node-set()拡張機能を使用する必要がある場合があります。

上記には、詳しく説明できるいくつかの側面があります。行き詰まったら大声で!HTH。

PS実際、私がこの投稿を開始して以来、@Sean は彼の回答を投稿しました。上記のスタイルシートを適用するよりもはるかに使いやすいです。

于 2012-07-24T01:36:02.733 に答える