4

私はこれを行うための最良の(効率的な)方法を見つけようとしています。

中サイズのXMLドキュメントがあります。特定の設定に応じて、セキュリティ上の理由から、その特定の部分を除外する必要があります。

XSLTは構成可能であり、コードを変更する必要がないため、これをXSLTで実行します。

私は周りを見回しましたが、あまり運が良くありません。

例えば:

私は次のXPathを持っています:

//*[@root='2.16.840.1.113883.3.51.1.1.6.1']

Whicroothは、特定のOIDに等しいルート属性を持つすべてのノードを提供します。これらのノードでは、いくつか(例: foobar )を除くすべての属性を消去してから、別の属性(例:reason)を追加したいと思います。

また、特定の属性を持つノードに関して、特定のノードでゼロダウンし、同様の方法でその内容をクリアするために実行できる複数のXPath式が必要です。

私は以下からの情報で遊んでいます:

特定のリストを除くすべてのXML子ノードを選択するXPath式?

XSLパラメータごとに名前で要素や属性を削除します

これまでに行ったことにアクセスできるようになり次第、更新されます。

例:

変換前のXML。 UPdate:拡張機能を除外してから、その拡張機能属性の値と一致するドキュメント内のすべての値を除外します。

<root>
    <childNode>
        <innerChild root="2.16.840.1.113883.3.51.1.1.6.1" extension="123" type="innerChildness"/>
        <innerChildSibling/>
    </childNode>
    <animals>
     <cat>
       <name>123</name>
     </cat>
    </animals>
    <tree/>
    <water root="2.16.840.1.113883.3.51.1.1.6.1" extension="1223" type="liquidLIke"/>
</root>

<root>
    <childNode>
        <innerChild root="2.16.840.1.113883.3.51.1.1.6.1" flavor="MSK"/> <!-- filtered -->
        <innerChildSibling/>
    </childNode>
    <animals>
      <cat>
        <name>****</name>
       </cat> <!-- cat was filtered -->
    </animals>
    <tree/>
    <water root="2.16.840.1.113883.3.51.1.1.6.1" flavor="MSK"/> <!-- filtered -->
</root>

XSLT2を使用できます。

私は運がなくてこれを試しています(初心者向け)

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

    <xsl:param name="OIDAttrToDelete" select="'extension'"/>

    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <!-- Get all nodes for the OID -->
    <xsl:template match="//*[@root='2.16.840.1.113883.3.51.1.1.6.1']">
        <xsl:if test="name() = $OIDAttrToDelete">
            <xsl:attribute name="nullFlavor">MSK</xsl:attribute>
            <xsl:call-template name="identity"/>            
        </xsl:if>
    </xsl:template>    
</xsl:stylesheet>
4

2 に答える 2

2
<xsl:param name="OIDAttrToDelete" select="'extension'" />

<xsl:template match="* | node()">
  <xsl:copy>
    <xsl:apply-templates select="* | node()" />
  </xsl:copy>
</xsl:template>

<xsl:template match="@*">
  <xsl:choose>
    <xsl:when test="../@root = '2.16.840.1.113883.3.51.1.1.6.1'">
      <xsl:copy-of select=".[not(contains($OIDAttrToDelete, name()))]" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy-of select=".">
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

ノート:

属性のみに一致するテンプレートを作成し、それらをコピーするかどうかを決定します。このようにして、IDテンプレートにあまり干渉する必要はありません。

IDテンプレートに名前を付ける必要はありません。適切なselect式を使用して呼び出すだけ<apply-templates>で、プロセッサが自動的に呼び出します。

テンプレートの一致式は完全なXPath式ではありません。一致する必要はありません//*[predicate]。使用*[predicate]するだけで十分です。

セキュリティ上の懸念が理由である場合は、$OIDAttrToKeep代わりにホワイトリスト()を検討します。

が値$OIDAttrToDeleteのリスト(たとえば、コンマ区切り)の場合、テストに区切り文字を含める必要があります。

.[
  not(
    contains(
      concat(',', $OIDAttrToDelete, ','), 
      concat(',', name(), ',') 
    )
  )
]

名前の部分的な一致を避けるため。

親OIDを構成可能にする必要がある場合は、同じ手法を使用できます。

<xsl:template match="@*">
  <xsl:choose>
    <xsl:when test="
      contains(
        concat(',', $OIDToStrip, ','),
        concat(',', ../@root, ',')
      )
    ">
    <!-- ... -->
    </xsl:when>
  </xsl:choose>
</xsl:template>
于 2012-06-18T21:56:37.013 に答える
2

これは完全なXSLT2.0変換であり、外部パラメーターに従って、特定の属性名と値を持つ要素を識別し、そのような要素ごとに、ホワイトリストに登録されていないすべての属性を削除し、他の指定された属性を追加します

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="vFilters">
     <filter>
      <markerAttribute name="root">2.16.840.1.113883.3.51.1.1.6.1</markerAttribute>
      <whiteListedAttributes>
        <name>root</name>
        <name>foo</name>
      </whiteListedAttributes>
      <addAtributes flavor="MSK" reason="Demo"/>
     </filter>
 </xsl:param>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match=
 "*[for $cur in .,
        $m in $vFilters/filter/markerAttribute
     return
        $cur/@*[name() eq $m/@name and . eq $m]
   ]">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:copy-of select=
     "for $m
           in $vFilters/filter/markerAttribute
       return
         if(current()/@*
                      [name() eq $m/@name
                     and
                      . eq $m
                      ])
           then
             $m/../addAtributes/@*
           else ()
     "/>
    <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

  <xsl:template match=
 "@*[for $cur in .,
         $p in ..,
         $m in $vFilters/filter/markerAttribute
     return
          $p/@*[name() eq $m/@name and . eq $m]
         and
          not(name($cur) = $m/../whiteListedAttributes/name)
    ]
  "/>
</xsl:stylesheet>

この変換が次のXMLドキュメントに適用される場合(提供されているが、ホワイトリストに登録されている属性が1つ追加されている):

<root>
    <childNode>
        <innerChild root="2.16.840.1.113883.3.51.1.1.6.1"
          a="b" b="c" foo="bar" type="innerChildness"/>
        <innerChildSibling/>
    </childNode>
    <animals>
        <cat>
            <name>bob</name>
        </cat>
    </animals>
    <tree/>
    <water root="2.16.840.1.113883.3.51.1.1.6.1"
    z="zed" l="ell" type="liquidLIke"/>
</root>

必要な正しい結果が生成されます。識別された要素で、ホワイトリストに記載されていないすべての属性が削除され、フィルターで指定された2つの新しい属性が追加されます。

<root>
      <childNode>
            <innerChild root="2.16.840.1.113883.3.51.1.1.6.1" foo="bar" flavor="MSK" reason="Demo"/>
            <innerChildSibling/>
      </childNode>
      <animals>
            <cat>
                  <name>bob</name>
            </cat>
      </animals>
      <tree/>
      <water root="2.16.840.1.113883.3.51.1.1.6.1" flavor="MSK" reason="Demo"/>
</root>

説明

外部パラメーター$vFiltersには、次のように1つ以上のフィルターを含めることができます。

 <filter>
  <markerAttribute name="root">2.16.840.1.113883.3.51.1.1.6.1</markerAttribute>
  <whiteListedAttributes>
    <name>root</name>
    <name>foo</name>
  </whiteListedAttributes>
  <addAtributes flavor="MSK" reason="Demo"/>
 </filter>

このmarkerAttribute要素は、識別属性の名前と値を指定します。この場合、フィルターはroot、値が。である属性を持つ要素を識別します(対象です) "2.16.840.1.113883.3.51.1.1.6.1"

このフィルターで指定されているホワイトリストに登録された属性名は2つあります:rootfoo

このフィルター要素によって識別されるすべてに、指定された値を持つ2つの新しい属性が追加されflavor="MSK"ますreason="Demo"

外部パラメーターには多くの$vFiltersフィルターを含めることができ、それぞれが要素の異なる「タイプ」を識別し、ホワイトリストに登録された属性名と追加する新しい属性の異なるセットを指定します。

于 2012-06-19T03:29:04.680 に答える