XSLT-删除节点+;与Xpath匹配的属性
我正在努力找到做这件事的最佳(有效)方法 我有一个中等大小的XML文档。根据特定设置,出于安全原因,需要过滤掉其中的某些部分 我将在XSLT中这样做,因为它是可配置的,不需要更改任何代码 我环顾四周,但运气不太好 例如: 我有以下XPath:XSLT-删除节点+;与Xpath匹配的属性,xslt,xpath,xslt-2.0,Xslt,Xpath,Xslt 2.0,我正在努力找到做这件事的最佳(有效)方法 我有一个中等大小的XML文档。根据特定设置,出于安全原因,需要过滤掉其中的某些部分 我将在XSLT中这样做,因为它是可配置的,不需要更改任何代码 我环顾四周,但运气不太好 例如: 我有以下XPath: //*[@root='2.16.840.1.113883.3.51.1.1.6.1'] Whicrooth为我提供了根属性等于特定OID的所有节点。在这些节点中,我希望删除除少数属性(例如foo和bar)之外的所有属性,然后添加另一个属性(例如reaso
//*[@root='2.16.840.1.113883.3.51.1.1.6.1']
Whicrooth为我提供了根属性等于特定OID的所有节点。在这些节点中,我希望删除除少数属性(例如foo和bar)之外的所有属性,然后添加另一个属性(例如reason)
我还需要有多个XPath表达式,这些表达式可以在特定节点上运行到零,并以类似的方式清除具有特定属性的节点的内容
我在玩弄以下信息:
及
当我能够访问到我迄今为止所做的事情时,将很快更新
例如:
转换前的XML。
更新:我想过滤掉扩展名,然后过滤掉文档中与该扩展名属性值匹配的所有值:
<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>
123
之后
****
我能够使用XSLT2
我尝试这一点没有任何运气(首先)
MSK
以避免部分名称匹配
如果您的父OID应该是可配置的,则可以使用相同的技术:
<xsl:template match="@*">
<xsl:choose>
<xsl:when test="
contains(
concat(',', $OIDToStrip, ','),
concat(',', ../@root, ',')
)
">
<!-- ... -->
</xsl:when>
</xsl:choose>
</xsl:template>
这里是一个完整的XSLT 2.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>
markerAttribute
元素指定标识属性的名称和值。在这种情况下,过滤器标识(用于)具有根属性的元素,其值为“2.16.840.1.113883.3.51.1.1.6.1”
此筛选器中指定了两个白名单属性名:root
和foo
将在此过滤器元素标识的每个过滤器上添加两个具有指定值的新属性:flavor=“MSK”
和reason=“Demo”
外部参数$vFilters
可以包含许多过滤器,每个过滤器识别不同的“类型”元素,并指定一组不同的白名单属性名称和要添加的新属性。最终我希望的是能够添加(一旦我了解了更多信息……我不是XSLT专家)附加过滤器以过滤XML。维护比每次更新代码更容易。因此每次都可能有不同的规则。Ryan Ternier:在XSLT 2.0转换中实现所有这些要求并不太具挑战性。嘿,Tomalak,是的,我将以白色列出要保留的属性。谢谢。现在要测试这一点需要花费100万美元s解析文档嘿,伙计,谢谢你的帮助。我已经用一个额外的位更新了这个问题。你知道用你的一个模板是否可行吗?@Ryan添加两个模板。第一个:
使用
通过
过滤其输出。第二个空的:
删除t中的任何扩展属性他输入。我不知道XSLT可以做到这一点!谢谢。这需要4毫秒来解析文档。@RyanTernier:不客气。在使用此解决方案时,您还有什么问题吗?它们都很好用-谢谢。XSLT中使用了什么脚本语言?这是XSLT的通用脚本语言吗?@RyanTernier:这是标准XSLT 2.0--没有使用任何扩展。您可能对匹配模式感到疑惑——这些都是绝对有效的。XPath 2可能对您来说似乎很奇怪——这是XSLT 2的基础,并且每个兼容的XSLT 2处理器实现XPath 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>
.[
not(
contains(
concat(',', $OIDAttrToDelete, ','),
concat(',', name(), ',')
)
)
]
<xsl:template match="@*">
<xsl:choose>
<xsl:when test="
contains(
concat(',', $OIDToStrip, ','),
concat(',', ../@root, ',')
)
">
<!-- ... -->
</xsl:when>
</xsl:choose>
</xsl:template>
<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>
<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>
<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>
<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>