[英]XSLT to remove all but certain nodes from the following type of XML structure
<Rootnode>
<Properties Attribute ="xxx">
<Type>1</Type>
<Size>10</Size>
</Properties>
<Other>
<blah>h</blah>
</Other>
<Other2>
<blah>h</blah>
</Other2>
<Properties Attribute ="xxx">
<xType>5</xType>
<xSize>10</xSize>
</Properties>
<Items>
<Item4>8</Item4>
</Items>
<Items>
<Item6>8</Item6>
</Items>
<Properties Attribute ="xxx">
<zType>1</zType>
<zSize>10</zSize>
</Properties>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>
現在,我只想包含屬性和項目。 優選地,如果屬性是相同的名稱和值,則將屬性和項目組連接在一起,並基於屬性對屬性和項目進行排序,並按字母順序對兩個子節點進行排序。 到目前為止,我還是一片空白;(
所需的輸出幾乎與ABach所示的一樣。 盡管我忘了提到的一件事是,每個“屬性”或“項目”上可能還有其他屬性,並且我知道我希望排序的屬性的名稱。 我可以很容易地修改。
即所需的輸出
<?xml version="1.0"?>
<Rootnode>
<Properties Attribute="xxx">
<Size>10</Size>
<Type>1</Type>
<xSize>10</xSize>
<xType>5</xType>
<zSize>10</zSize>
<zType>1</zType>
</Properties>
<Items>
<Item4>8</Item4>
<Item6>8</Item6>
</Items>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>
很抱歉,到目前為止我沒有付出很多努力。。。我陷入了混亂,認為並沒有多大幫助。。。
正如@LarsH所指出的那樣,通過不向我們顯示期望的輸出XML,我們可以猜測您真正想要的是什么。 就是說,這是我對XSLT 1.0解決方案的嘗試。
當此XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key
name="PropertiesByAttributeNameVal"
match="Properties"
use="concat(name(@*[1]), '+', @*[1])" />
<xsl:key
name="ItemsByAttributeNameVal"
match="Items"
use="concat(name(@*[1]), '+', @*[1])" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Rootnode">
<Rootnode>
<xsl:apply-templates
select="Properties[
generate-id() =
generate-id(key(
'PropertiesByAttributeNameVal',
concat(name(@*[1]), '+', @*[1]))[1])]">
<xsl:with-param name="pKeyName"
select="'PropertiesByAttributeNameVal'" />
<xsl:sort select="concat(name(@*[1]), '+', @*[1])" />
</xsl:apply-templates>
<xsl:apply-templates
select="Items[
generate-id() =
generate-id(key(
'ItemsByAttributeNameVal',
concat(name(@*[1]), '+', @*[1]))[1])]">
<xsl:with-param name="pKeyName"
select="'ItemsByAttributeNameVal'" />
<xsl:sort select="concat(name(@*[1]), '+', @*[1])" />
</xsl:apply-templates>
</Rootnode>
</xsl:template>
<xsl:template match="Properties|Items">
<xsl:param name="pKeyName" />
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates
select="key($pKeyName, concat(name(@*[1]), '+', @*[1]))/*">
<xsl:sort select="name()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
...針對提供的XML運行:
<Rootnode>
<Properties Attribute="xxx">
<Type>1</Type>
<Size>10</Size>
</Properties>
<Other>
<blah>h</blah>
</Other>
<Other2>
<blah>h</blah>
</Other2>
<Properties Attribute="xxx">
<xType>5</xType>
<xSize>10</xSize>
</Properties>
<Items>
<Item4>8</Item4>
</Items>
<Items>
<Item6>8</Item6>
</Items>
<Properties Attribute="xxx">
<zType>1</zType>
<zSize>10</zSize>
</Properties>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>
...我猜是生成了正確的輸出XML:
<?xml version="1.0"?>
<Rootnode>
<Properties Attribute="xxx">
<Size>10</Size>
<Type>1</Type>
<xSize>10</xSize>
<xType>5</xType>
<zSize>10</zSize>
<zType>1</zType>
</Properties>
<Items>
<Item4>8</Item4>
<Item6>8</Item6>
</Items>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>
請注意,如果對稍有修改的XML文檔(具有更多分組等)運行相同的XSLT:
<?xml version="1.0" encoding="utf-8"?>
<Rootnode>
<Properties Attribute="xxx">
<Type>1</Type>
<Size>10</Size>
</Properties>
<Other>
<blah>h</blah>
</Other>
<Other2>
<blah>h</blah>
</Other2>
<Properties Attribute="yyy">
<xType>5</xType>
<xSize>10</xSize>
</Properties>
<Items>
<Item4>8</Item4>
</Items>
<Items place="US">
<Item9>8</Item9>
</Items>
<Items>
<Item1>8</Item1>
</Items>
<Properties Attribute2="xxx">
<zType>1</zType>
<zSize>10</zSize>
</Properties>
<Properties Attribute="xxx">
<elephantType>5</elephantType>
<elephantSize>15</elephantSize>
</Properties>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>
...再一次,我認為是正確的答案產生了:
<?xml version="1.0"?>
<Rootnode>
<Properties Attribute="xxx">
<Size>10</Size>
<Type>1</Type>
<elephantSize>15</elephantSize>
<elephantType>5</elephantType>
</Properties>
<Properties Attribute="yyy">
<xSize>10</xSize>
<xType>5</xType>
</Properties>
<Properties Attribute2="xxx">
<zSize>10</zSize>
<zType>1</zType>
</Properties>
<Items>
<Item1>8</Item1>
<Item4>8</Item4>
</Items>
<Items place="UK">
<Item1>8</Item1>
</Items>
<Items place="US">
<Item9>8</Item9>
</Items>
</Rootnode>
假設:
<Properties>
和<Items>
元素都只有一個屬性,並且它應該是分組確定器。 說明:
因為這是XSLT 1.0解決方案, Muenchian Grouping
是在唯一選擇器下對節點和屬性進行分組時的日常工作。 因此,我們定義了兩個鍵:一個用於<Properties>
元素,另一個用於<Items>
元素。
第一個模板是Identity Transform
-其工作是將所有文檔從源文檔按原樣輸出到結果文檔。
第二個模板與<Rootnode>
元素匹配。 指示僅將模板應用於首先出現在各自鍵中的那些<Properties>
和<Items>
元素。 這具有僅處理唯一元素的預期效果(基於它們的第一個屬性的名稱和值)。
指定<xsl:apply-templates>
元素后,請注意,在兩種情況下,都將指示該屬性按相同的屬性名稱/值對對結果進行排序。
請注意,每個<xsl:apply-templates>
元素都有一個參數(通過<xsl:with-param>
)。 正如您將看到的,用於處理<Properties>
和<Items>
元素的代碼幾乎是相同的。 唯一的區別是我們從中獲取結果的關鍵。 因此,我選擇將該邏輯合並到第三個模板中,並通過此參數說明可變性。
第三個模板匹配<Properties>
和<Items>
元素。 對於每個節點,將復制原始節點(及其屬性)。 最后,將模板應用於此元素的所有子元素([此時,基於子元素本身的名稱]進行了適當的排序)。
如果您已經有了東西而不是一無所有,那么您將更有可能獲得幫助。 首先,創建一個與Properties和Items相匹配的模板( match="Properties | Items"
),其內容只是復制匹配的元素: <xsl:copy-of select="." />
<xsl:copy-of select="." />
。
這將為您顯示一些工作代碼。
我建議的下一步是發布所需輸出的樣本,以及XSLT代碼給出的實際輸出。
這將使人們在回答您的問題時彌合的差距大大縮小。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.