2016-09-08 48 views
0

我生成一個XML文件,並希望創造一些變換,將插入以下到根元素的RewriteRules:斯卡拉重寫規則來設置命名空間和schemaLocation?

<content 
    xmlns:ns="http://example.com/ns" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://example.com/ns http://example.com/xml/xsd/xml-schema-articles-v1.0.xsd"> 

它看起來from this gist在設定xmls:ns命名空間創建一個NamespaceBinding和應用的問題作爲Elem的範圍。然而,我還沒有成功爲此創建了一個RewriteRule,而且我仍然在尋找如何添加模式實例(xmlns:xsi)和schemaLocation。

+0

你怎麼生成你的XML? – mfirry

+0

我實際上是從文件中讀取舊的xml,並使用一堆scala.xml.transform RewriteRules來修改它。 – doub1ejack

回答

0
// start with a sample xml 'document' 
val xml = <root attr="willIStayOrWillIGoAway"><container/></root> 

// create a namespace binding using TopScope as the "parent" argument 
val ns = new NamespaceBinding("ns", "http://example.com/ns", TopScope) 

// create a second namespace binding, and pass "ns" as the new parent argument 
val xsi = new NamespaceBinding("xsi", "http://www.w3.org/2001/XMLSchema-instance", ns) 

請注意,我們做了兩個NamespaceBindings,而是因爲他們被「鏈接」在一起,我們只需要最後一個傳遞給我們的RuleTransformer類。

// the schemaLocation needs to be a PrefixedAttribute 
val schemaLoc = new PrefixedAttribute("xsi", "schemaLocation", "http://example.com/ns http://example.com/xml/xsd/xml-schema-articles-v1.0.xsd", Null) 

xmlns:nsxmlns:xsi屬性實際上NamespaceBindings - 我不知道他們爲什麼不同的處理。但xsi:schemaLocation實際上是一個範圍屬性,所以我們使用PrefixedAttribute

// in order to limit the insertion to the root node, you'll need it's label 
val rootNodeLabel = "root" 

// make a new RewriteRule object 
val setSchemaAndNamespaceRule = new setNamespaceAndSchema(rootNodeLabel, xsi, schemaLoc) 

// apply the rule with a new transformer 
val newxml = new RuleTransformer(setSchemaAndNamespaceRule).transform(xml).head 

應用變壓器返回這個。

newxml: scala.xml.Node = 
    <root attr="willIStayOrWillIGoAway"  
     xmlns:ns="http://example.com/ns" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://example.com/ns http://example.com/xml/xsd/xml-schema-articles-v1.0.xsd">> 
    <container/> 
    </root> 

而這是返回重寫規則的類。

// new class that extends RewriteRule 
class setNamespaceAndSchema(rootLabel: String, ns: NamespaceBinding, attrs: MetaData) extends RewriteRule { 
    // create a RewriteRule that sets this as the only namespace 
    override def transform(n: Node): Seq[Node] = n match { 

    // ultimately, it's just a matter of setting the scope & attributes 
    // on a new copy of the xml node 
    case e: Elem if(e.label == rootLabel) => 
     e.copy(scope = ns, attributes = attrs.append(e.attributes)) 
    case n => n 
    } 
} 

請注意,我們的原始屬性保留;看看我們的擴展RewriteRule類如何附加schemaLocation屬性,而不是直接使用它。